Copyright © 1999-2008, Agent Oriented Software Pty. Ltd.

JACK™ Intelligent Agents Agent Manual

Release 5.2
18 May 2006


Table of Contents

Publisher Information

 Agent Oriented Software Pty. Ltd.  
 P.O. Box 639,  
 Carlton South, Victoria, 3053  
 AUSTRALIA  
   
Phone: +61 3 9349 5055
Fax: +61 3 9349 5088
Web:  http://www.agent-software.com

If you find any errors in this document or would like to suggest improvements, please let us know.

The JACK™ documentation set includes the following manuals and practicals:

Document Description
Agent Manual Describes the JACK programming language and infrastructure. JACK can be used to develop applications involving BDI agents.
Teams Manual Describes the JACK Teams programming language extensions. JACK Teams can be used to develop applications that involve coordinated activity among teams of agents.
Development Environment Manual Describes how to use the JACK Development Environment (JDE). The JDE is a graphical development environment that can be used to develop JACK agent and team-based applications.
JACOB Manual Describes how to use JACOB. JACOB is an object modelling language that can be used for inter-process transport and object initialisation.
WebBot Manual Describes how to use the JACK WebBot to develop JACK enabled web applications.
Design Tool Manual Describes how to use the Design Tool to design and build an application within the JACK Development Environment.
Graphical Plan Editor Manual Describes how to use the Graphical Plan Editor to develop graphical plans within the JACK Development Environment.
JACK Sim Manual Describes how to use the JACK Sim framework for building and running repeatable agent simulations.
Tracing and Logging Manual Describes the tracing and logging tools available with JACK.
Agent Practicals A set of practicals designed to introduce the basic concepts involved in JACK programming.
Teams Practicals A set of practicals designed to introduce the basic concepts involved in Teams programming.


1 Introduction

1.1 Background

JACK™ Intelligent Agents (JACK) is an Agent Oriented development environment built on top of and integrated with the Java programming language. It includes all components of the Java development environment as well as offering specific extensions to implement agent behaviour. JACK's relationship to Java is analogous to the relationship between the C++ and C languages. C was developed as a procedural language and subsequently C++ was developed to provide programmers with object-oriented extensions to the existing language. Similarly, JACK has been developed to provide agent-oriented extensions to the Java programming language. JACK source code is first compiled into regular Java code before being executed.

In the same way that object-oriented programming introduces a number of key concepts that influence the entire logical and physical structure of the resulting software system, so too does agent-oriented programming. In agent-oriented programming, a system is modelled in terms of agents. These agents are autonomous reasoning entities capable of making pro-active decisions while reacting to events in their environment.

1.2 Agent Oriented Concepts

Agent oriented programming is an advanced software modelling paradigm that arose from research in distributed artificial intelligence. It addresses the need for software systems to exhibit rational, human-like behaviour in their respective problem domains. Traditional software systems make it difficult to model rational behaviour, and often programs written in these systems experience limitations, especially when attempting to operate in real-time environments.

Agent oriented programming is highly suited to many application areas, including distributed business systems, command and control, intelligent appliances and simulation. Although still young and under development, it has already shown particular promise in a variety of distributed problem solving tasks such as fleet organisation, air traffic management and air combat simulation. Because it offers such a modular and elegant solution to many of the problems faced in reactive processing, agent-oriented programming is ideally suited to these environments.

The Agent Oriented model follows the same underlying principle as Object Oriented programming – that reliable and scalable development can be enhanced by encapsulating the desired behaviour in modular units which contain all the definitions and structures required for them to operate independently. Agents extend the concept of encapsulation to include a representation of behaviour at a higher level than object-oriented approaches.

1.2.1 What is an Agent?

The term agent is widely used to describe a range of software components, varying in capability from procedural wizards, found in popular desktop applications, to information agents that are used to automate information search and retrieval, and, finally, to intelligent agents capable of reasoning in a well-defined way. The agents used in JACK are intelligent agents. They model reasoning behaviour according to the theoretical Belief Desire Intention (BDI) model of artificial intelligence.

Following the BDI model, JACK intelligent agents are autonomous software components that have explicit goals to achieve or events to handle (desires). To describe how they should achieve these desires, BDI agents are programmed with a set of plans. Each plan describes how to achieve a goal under varying circumstances. Set to work, the agent pursues its given goals (desires), adopting the appropriate plans (intentions) according to its current set of data (beliefs) about the state of the world. This combination of desires and beliefs initiating context-sensitive intended behaviour is part of what characterises a BDI agent.

A JACK agent is a software component that can exhibit reasoning behaviour under both pro-active (goal directed) and reactive (event driven) stimuli. Each agent has:

When an agent is instantiated in a system, it will wait until it is given a goal to achieve or experiences an event that it must respond to. When such a goal or event arises, it determines what course of action it will take. If the agent already believes that the goal or event has been handled (as may happen when it is asked to do something that it believes has already been achieved), it does nothing. Otherwise, it looks through its plans to find those that are relevant to the request and applicable to the situation. If it has any problems executing this plan, it looks for others that might apply and keeps cycling through its alternatives until it succeeds or all alternatives are exhausted.

Thus, an agent can be thought of as analogous to a person with access to a Procedures Manual. The Procedures Manual (set of plans) describes the steps that the agent should take when a certain event arises or when it wants to achieve a certain outcome. At first glance, this may seem like ordinary Expert System behaviour – with all the limitations that this implies. However, the crucial difference in agent-oriented systems is that the agent is able to be programmed to execute these plans just as a rational person would. In particular, it is able to exhibit the following properties associated with rational behaviour:

1.2.2 Why program using Agents?

The capability of intelligent agents to autonomously perform simple tasks has aroused much interest. The key characteristics that make them attractive are their:

JACK agents are highly suited to the development of time and mission-critical systems, as the BDI approach provides for the verification and validation of the model. The agent's goals may include keeping human users informed of what the agent is trying to achieve, what its current intentions are, and what progress it has been able to make. Giving BDI agents pre-compiled plans is a method of ensuring predictable behaviour under critical operational conditions, and of ensuring performance.

1.3 The Components of JACK

1.3.1 The JACK Agent Language

The JACK Agent Language is the actual programming language used to describe an agent-oriented software system. The JACK Agent Language is a super-set of Java – encompassing the Java syntax while extending it with constructs to represent agent-oriented features.

Each of the Java extensions that are included in JACK, along with their expected usage and semantic behaviour, are described in detail in the following chapters.

1.3.2 The JACK Agent Compiler

The JACK Agent Compiler pre-processes JACK Agent Language source files and converts them into pure Java. This Java source code can then be compiled into Java virtual machine code to run on the target system.

1.3.3 The JACK Agent Kernel

The JACK Agent Kernel is the runtime engine for programs written in the JACK Agent Language. It provides a set of classes that give JACK Agent Language programs their agent-oriented functionality. Most of these classes run behind the scenes and implement the underlying infrastructure and functionality that agents require, while others are used explicitly in JACK Agent Language programs, inherited from and supplemented with callbacks as required to provide agents with their own unique functionality.

1.4 Developing a JACK Application

An integrated development environment known as the JACK Development Environment is available for the development of JACK applications. Use of the JACK development environment is described in a separate manual. Alternatively, JACK applications can be developed from the command line using an editor of choice and explicitly invoking the JACK Agent compiler.

If the latter choice is used, the environment will need to be set up. The following section explains how this is done for the more common operating environments. The instructions that follow assume that all commands are invoked from a command line. Thus, under Windows or NT, a DOS window will need to be created.

1.4.1 Setting up your Environment

Before a JACK application can be compiled and run, ensure that the PATH and CLASSPATH variables are set correctly. PATH needs to be set so that java and javac are accessible. CLASSPATH needs to be set so that java and javac can access the JACK class files and the classes that are created.

The actual settings for PATH and CLASSPATH will depend upon where the java executables and JACK classes have been installed. It is assumed that:

  1. The PATH variable is set correctly.
  2. The CLASSPATH variable has not been set. (If it has, it may need to be extended. This procedure is operating system dependent.)

    set CLASSPATH=C:\aos\lib\jack.jar;.
      CLASSPATH=/aos/jack/lib/jack.jar:.
      export CLASSPATH
      setenv CLASSPATH=/usr/local/aos/jack/lib/jack.jar:.

1.4.2 Source Code Creation

This can be achieved either using the JACK development environment, or an editor of choice. When developing a JACK application, source code will be created for some or all of the following entities:

plus a Java class that contains the application main() function that is the entry point for the Java virtual machine and any other Java file required by this application.

The files that are created for these entities must have the same base name as the entity defined in the file. They may have an extension designating the type of JACK entity contained, or simply a .jack extension.

Extension Usage
 .jack Any JACK object definition.
 .agent JACK agent definition.
 .cap JACK capability definition.
 .plan JACK plan definition.
 .event JACK event definition.
 .bel JACK beliefset definition.
 .view JACK view definition.
 .java Java class or interface definition.

Table 1-1: JACK file extensions

1.4.3 Compilation

Assuming that all the source files are in your current directory, the application can be compiled by invoking JackBuild:

    java aos.main.JackBuild

This runs the JackBuild utility which in this invocation compiles all of the JACK source files in the current directory into Java source. The Java compiler is then automatically invoked on all Java source files in the current directory. JackBuild recognises JACK files by their file name extensions as listed in the previous section.

Without arguments, the JackBuild utility assumes that all files in the directory belong to the application. If the application is organised into subdirectories, it can be compiled by invoking JackBuild from the parent directory as follows:

    java aos.main.JackBuild -r

The -r option recursively enters subdirectories to compile code.

Refer to Appendix A for more information about JackBuild.

1.4.4 Running a JACK Application

If one assumes that the main() method was in a file called Test.java, the compilation process will have produced a file called Test.class. The application can then be run from the directory containing Test.class by typing

    java Test


Note: It is possible to configure Windows so that files with the extension .class are runnable by point-and-click.

The programmer can specify command line arguments for use within an application. Note that there are some command line arguments which are processed internally by JACK. In particular, a DCI network from the command line can be set up (this is discussed further in the chapter on Inter-agent Communication). If such arguments are present, the method aos.jack.Kernel.init() must be used to process these arguments before any user specified command line arguments are processed. init() extracts and processes command line arguments intended for JACK, then returns a modified argument list containing the remaining user defined arguments. This list can then be accessed in the normal way, as shown in the example below:

    public class Example
    {
      // The user supplies a single numeric command line argument
      // in addition to those which will be handled by JACK
      public static void main(String args[])
      {
        args = aos.jack.Kernel.init(args);

        int snum = Integer.parseInt(args[0]);
         :
         :
      }
    }

All the standard Java command options are available. Some JACK functionality such as the interaction diagram and debugging is configurable via the system properties file. The -D option can be used in these circumstances to set properties. For more details on the interaction diagram and debugging refer to the Tracing and Logging Manual.

1.4.5 Debugging a JACK Application

There are a number of tools available to assist the developer during application development. These range from graphical tracing tools to logging tools which provide a detailed trace of system execution. These tracing and logging tools are described in the Tracing and Logging Manual.


2 JACK Agent Language Overview

2.1 The JACK Agent Language

The JACK Agent Language is built on top of Java. Like C++, the JACK Agent Language does more than extend the functionality of Java – it also provides a framework to support an entirely new programming paradigm. The JACK Agent Language is an Agent Oriented programming language and is used for implementing Agent Oriented software systems.

The JACK Agent Language extends Java to support Agent Oriented programming:

All the language extensions are implemented as Java plug-ins. This makes the language as extensible and flexible as possible. Flexibility is important in the JACK Agent Language because it facilitates ongoing research into agent-oriented programming. Developers may, for example, want to investigate how different beliefset implementations affect agent performance. Because the beliefset component is supplied as a plug-in, this can be altered with minimal changes to the JACK development environment. All that is required is to replace the beliefset implementation in the kernel package.

Each of the JACK Agent Language extensions is strictly typed. This minimises implicit type casting and the opportunity for programmer error. Strict typing also allows for more efficient program compilation by the JACK Agent Compiler.

2.1.1 Class, Interface and Method Extensions

The JACK Agent Language introduces five main class-level constructs. These constructs are:

For a detailed description of each of these extensions, including the specific interfaces and methods provided with them, refer to the appropriate chapters in this manual.

2.1.2 Syntactic Extensions

JACK Agent Language provides a number of variations and extensions to the standard Java syntax. These extensions exist purely to support the syntactic and semantic differences between object-oriented and agent-oriented programming.

An example piece of code written in the JACK Agent Language to implement an agent plan is given below. The syntactic elements that are unique to JACK Agent Language have been highlighted in bold. All other elements follow normal Java syntax.

    plan MovementResponse extends Plan
    {
       #handles event RobotMoveEvent moveResponse;
       #uses agent implementing RobotInterface robot;

       static boolean relevant (RobotMoveQEvent ev)
       {
          return (ev.ID == RobotMoveQEvent.REPLY_SAFE ||
              ev.ID == RobotMoveQEvent.REPLY_DEAD);
       }

       body()
       {
          if (moveResponse.ID==REPLAY_SAFE)
          {
             System.err.println("Robot Safe to Move");
             robot.updatePosition(moveResponse.Lane,
             moveResponse.Displacement);
          }
          else
          { // robot didn't make it
             System.err.println("Robot is Dead");
             robot.die();
          }
       }
    }

In this example, the plan being defined inherits its core functionality from the JACK Agent Language class: Plan. It then identifies how the plan will be used through a number of JACK Agent Language plan declarations. JACK Agent Language declarations are each preceded with a # symbol to distinguish them from Java syntax elements, for example #handles event and #uses agent implementing.

The #handles event declaration identifies the goal or event to which this plan will respond. The #uses agent implementing declaration constrains the agent(s) that can use this plan. Only those agents that present the specified interface (RobotInterface) can include this plan.

The block of code in this example contains only regular Java code. The JACK Agent Language however provides its own statements that can be used when required. These statements are known as reasoning method statements, and are identified by a preceding @ character. Reasoning methods specify operations that are only meaningful in agent-oriented programming, such as posting an event or waiting until the agent acquires a particular belief. They are called reasoning method statements because you can only use them in a reasoning method belonging to a plan. These reasoning methods describe the reasoning and behaviour that an agent undertakes when it executes an instance of that plan.

Hence, JACK Agent Language extends Java syntax at three levels:

For more information on the JACK Agent Language syntax extensions to Java, see the following chapters.

2.1.3 Semantic Extensions

Because agent-oriented programming follows a different modelling paradigm to object-oriented programming, there are significant differences in how programs written in each language behave at runtime.

The JACK Agent Language extends the Java execution engine in the following ways:

A detailed description on the semantic consequences of each new JACK Agent Language construct can be found in the appropriate chapters of this manual (Agents, Capabilities, Events, Plans, Beliefset Relations and Views).

2.2 JACK Agent Language Summary

The JACK Agent Language is closely related to Java and extends the regular Java syntax. It allows the programmers to develop the components that are necessary to define BDI agents and their behaviour. These functional units are:

Each of the events, plans and beliefsets used are implemented as Java classes. They inherit certain fundamental properties from a base class and extend these base classes to meet their own specific needs. The base classes are defined within the kernel and form the 'glue' that holds a JACK agent-oriented program together. However, the JACK Agent Language is more than just a specific organisation of Java objects and inheritance structures – it provides its own extended syntax, which has no analogous representation in Java.

JACK Agent Language constructs can be categorised as follows:

In addition, each of the JACK Agent Language classes supplies a number of normal Java members and methods that can be made use of in JACK programs.

The constructs available in each of these categories are listed in the following sub-sections.

2.2.1 JACK Agent Language Classes

These classes define functional units within JACK. The functional units are implemented as Java classes, with their agent-oriented properties embedded within the class as private methods. They also provide some base members and methods that JACK Agent Language programmers can use. Each JACK Agent Language type and the base members and methods it provides are listed below:

Note that a View does not have a base class.

2.2.2 JACK Agent Language Declarations (#-Declarations)

JACK Agent Language #-declarations define agent-oriented properties of a JACK Agent Language type, or relationships and dependencies that exist between JACK Agent Language types. They are used to specify relationships between classes in a JACK program. For example, JACK Agent Language declarations specify which plans an agent uses and which event a plan handles.

The range of #-declarations available in JACK Agent Language are listed below:

#chooses for event – is used in plan definitions to identify a plan that allows the agent to reason about which applicable plan instance it will execute for a given event occurrence. This is in contrast to normal plans, which describe how the agent will respond to a given event instance when that plan is selected. Because it provides the agent with the ability to reason about how it will respond to (reason about) a given event, plans that contain a #chooses for event declaration are known as meta-level reasoning plans.

#complex query – is used in view and beliefset definitions to define a complex query.

#exports data – is used in capability definitions to declare that a user-defined data structure or a JACK beliefset is exported from the capability so that it is accessible from its parent capability. The export statement can also be used to make a user-defined data structure or JACK beliefset available at the agent level, and hence accessible from other capabilities in the agent.

#function query – is used in view and beliefset definitions to define a function query.

#handles event – is used in agent definitions and plan definitions. In both cases, it identifies an event that an agent or plan handles. Event handling is declared in the agent that uses a plan and the plan itself. This allows JACK to perform type checking and ensure that the agent has at least one plan to handle every event that it claims to handle, and conversely that an agent doesn't have access to a plan that is beyond its stated event-handling responsibilities.

#handles external event – is used in capability definitions to declare that there are plans within the capability that handle events of a given type.

#has capability – is used in agent definitions and capability definitions. In an agent definition, it gives the agent access to all of the functional components enclosed by the capability. In a capability definition, it declares the use of an inner capability.

#imports data – is used in capability definitions to declare a user-defined data structure or JACK beliefset that is to be used within the capability, but is brought in from the enclosing capability or agent.

#indexed query / #linear query – are both used in beliefset definitions to specify how a relation can be queried. This declaration indicates which parameters it expects to be supplied in the query and which parameters it will need to return (through binding logical members) when the query succeeds.

#key field / #value field – are both used in beliefset definitions to specify the fields that belong to a relation. Key fields identify an object that the relation describes, while value fields identify attributes of that object.

#posted as – is used in an event definition to define a posting method for that event. An event's posting methods are used to construct instances of the event when the event needs to be posted. Multiple posting methods allow the event to be posted in different ways (even having different parameters) in different circumstances.

#posts event – is used in agent definitions, capability definitions and plan definitions to identify events that agent or plan is capable of posting. Neither an agent nor a plan can create an instance of an event unless they declare that they can post (#posts event) or send (#sends event) it. Whether an event is posted or sent depends on its type.

#posts external event – is used in capability definitions to declare that there are plans (or Java code) within this capability that post events of a given type.

#posted when – is added to an event definition to specify the condition which must arise for the event to be posted automatically.

#private data / #agent data / #global data – are used in agent definitions and capability definitions to identify a user-defined data structure or JACK beliefset that the agent can use to store information. A private data instance is unique to each agent, and hence can be read or modified by that agent and that agent only. An agent data instance is available to all agents of a given agent type (i.e. instances of the same Agent class). A global data instance is available to all agents in a given process. Agents should only modify the data that appears in their private user-defined data structures or in their private JACK beliefsets.

#propagates changes – marks that a beliefset may be a source beliefset in a team belief connection, and it provides an implementation of the connection dynamics, so that changes to the beliefset are propagated correctly. Belief propagation is only available when using JACK Teams. Refer to the Teams manual for more details.

#reasoning method – is used in plan definitions to define methods that an agent may execute when it runs this plan. Reasoning methods are different from normal Java methods in that they execute as finite state machines, and may succeed or fail, depending on whether the agent can complete each statement that they contain. The top-level reasoning method is called body(). This is the only reasoning method that must be present in all plans and is not preceded by an # symbol. The body() method can call other reasoning methods if they have been included amongst the plan's #reasoning method declarations. It can also initiate the execution of other tasks and subtasks by executing JACK Agent Language statements that post new events. Examples of such statements are: @subtask, @maintain and @achieve.

#reasoning method pass / fail – is used in plan definitions to identify processing that should occur after an instance of the plan has either succeeded or failed. When either of these methods is present in a plan, that plan's execution does not end when the plan has succeeded or failed. First, the relevant pass() or fail() method is executed.

#sends event – is used in agent definitions and plan definitions to identify message events that the agent or plan is capable of sending to other agents. Neither an agent nor a plan can send a message event to another agent unless it include a corresponding #sends event declaration for that class of message event.

#set behavior – is used in BDI event definitions to declare how an agent processes an instance of this event when it arises. Options that can be configured include whether the agent will re-try the event if an attempted plan fails and whether or not the agent can reason about which plan it executes in response to the event.

#set transport – is used to signal which transport format is to be used for message events.

#uses agent implementing – is used in plan definitions to declare that any agent using these plans must implement the required interface. Interfaces allow multiple agents to use a given plan.

#uses data / #reads data / #modifies data – are used in plan definitions to identify user-defined data structures and JACK beliefsets that the plan can access. If the plan reads a data instance it should only perform queries on it. If the plan modifies a data instance, it can read and modify the data. Similarly, if the plan uses a data instance, it can read and modify the data.

#uses data – is used in view definitions to declare that a view requires data of a specified type. It can also be added to event and plan definitions to provide access to a belief structure.

#uses interface – is used in plans to declare that one of the enclosing capabilities (or the enclosing agent) implements the required interface. Note that this declaration supersedes #uses agent implementing for most purposes.

#uses plan – is used in agent and capability definitions to specify that an agent or capability includes this plan in its set of available plans. This is a containment relationship.

#uses taskManager – is used in agent definitions to specify how an agent shares its processing capacity between active tasks. JACK provides a simple task manager, which persists with the current task until completion, and a round robin task manager which allows each task to execute a specified number of plan steps before switching to another waiting task.

2.2.3 Reasoning Method Statements (@-Statements)

Reasoning statements are JACK Agent Language specific statements that can only appear in reasoning methods. They describe actions that the agent can perform to execute behaviour. Steps such as posting events, sending messages to other agents or waiting until a particular condition is true are expressed using reasoning method statements.

Each reasoning method statement is listed below.

@action – is a reasoning statement that can be used if there is a need to include a lengthy computation within a plan.

@achieve – tells the agent to make a certain condition true. If the condition is already true, the agent does nothing, but if not a BDIGoalEvent will be posted. Typically, this event will initiate the execution of a plan to make the condition hold. The current plan is suspended while this plan is being executed, and the @achieve statement succeeds or fails based on whether the plan that is executed succeeds or fails.

@determine – tells the agent to find a binding for a logical condition that causes a BDIGoalEvent to succeed. Typically, the logical condition will contain one or more beliefset queries. For each binding that these queries return, the agent posts a BDIGoalEvent. As soon as one of these BDIGoalEvents succeeds, the @determine statement succeeds. If all bindings are tried and fail, the @determine statement fails.

@insist – tells the agent to ensure that a certain condition holds true. Like the @achieve statement, the agent will do nothing if the condition is already true and will post a BDIGoalEvent otherwise, but when the BDIGoalEvent has been handled, the agent re-tests the condition to ensure that it holds. If the condition holds, the @insist statement succeeds, but if not the BDIGoalEvent is posted again. The agent will keep testing the condition and posting the BDIGoalEvent until the specified condition is satisfied or the event processing fails.

@maintain – is used in a reasoning method to specify that a subtask be performed. However, while the agent is performing the subtask, it must ensure that a particular logical condition is never violated. If the logical condition is found to be false between plan steps, the subtask will fail immediately. Other than specifying a maintenance condition, the @maintain statement operates in exactly the same way as the @subtask statement (see below for details).

@parallel – allows concurrent sub-tasking of a set of statements within reasoning methods. The @parallel statement suspends execution of the calling plan while all enclosed statements are executed in parallel.

@post – posts an Event or BDIFactEvent within an agent. This initiates another task execution within the agent. The event is posted using one of its posting methods and is handled asynchronously by the current task execution thread.

@reply – sends a message event (MessageEvent or BDIMessageEvent) in response to another message event that the agent has received. It is only available in plans that are executed within a task initiated by the arrival of a message event. If the task execution was initiated by any other kind of event, the @reply statement will fail.

@send – sends a message event to another agent. Unlike the @post method which posts an event internally, an event is sent to another agent (potentially running in another process). The receiving agent then has the option of replying to the message. The sender has a mechanism for checking that a reply has been sent, and has methods for handling replies when they arrive.

@sleep – suspends execution of the task for a given period of time.

@subtask – posts an Event or BDIFactEvent , but instead of handling the event asynchronously in a separate task, the agent handles it synchronously as part of the same task.

@test – tests a condition. If the condition is true, it returns true. If the condition is false, it returns false. If the condition is unknown, it posts a BDIGoalEvent to find out whether it is true or false.

@wait_for – identifies a condition that the agent should wait for. The plan cannot proceed until this condition is true. The task is suspended, and waits until some other task performs an action that makes the condition true. To prevent the agent from waiting indefinitely, a timeout condition can also be specified.

2.2.4 Base Members and Methods

Each JACK Agent Language class offers a number of public members and methods that can be called in the user's programs. These base members and methods are listed below:

2.2.4.1 Agent Members

Timer timer – a public agent member that keeps the timer for this agent. This timer is used by the plan methods elapsed() and after(), and by the @sleep reasoning method statement.

2.2.4.2 Agent Methods

finish() – terminates the current agent instance. This is distinct from, and should not be confused with, the standard Java finalize() callback (used by the garbage collector to allow objects to take a final action before termination).

String name() – returns the full name of a given agent instance. An agent's full name takes the following form: local_name@portal_name, where:

void postEvent() – posts an event. The event is handled asynchronously by a separate task in the agent. This method behaves in the same way as the @post reasoning method statement. The postEvent() method allows Java code other than reasoning methods to initiate task execution within an agent by posting an event.

boolean postEventAndWait() – also posts an event. The event must belong to an event class that the agent has declared it can post (i.e. by identifying this class in one of its #posts event declarations). However, instead of posting the event asynchronously, the event is posted synchronously (as though it has been posted by a @subtask statement, for example), to be handled as a 'subtask' of the calling thread. The current execution thread stops what it is doing while the event is handled and waits for the event to either succeed or fail.

An attempt to call postEventAndWait() from a JACK thread (i.e. through a call chain originating in a plan) will be caught by the JACK kernel, which will issue a warning message. PostEventAndWait provides a means to post events synchronously from outside reasoning method execution (i.e. from a Java thread).

void reply(MessageEvent query, MessageEvent reply) – replies to a message event that an agent has received from another agent. It takes two message events as arguments:

An agent can reply to any message event that it receives. This method behaves identically to the @reply statement in the JACK Agent Language. Like send() and postEvent() , this method allows code outside plans to engage in inter-agent communication and to initiate task execution within an agent.

void send(String to, MessageEvent message) – sends a message event to another agent. It takes a message event and the (full) name of the agent to which it should be sent. Partial names resolve to the same portal as the sender.

2.2.4.3 Event Members

String from – appears in message events only, and enables identification of the agent that sent the message carried by this message event.

String message – appears in message events only (MessageEvents and BDIMessageEvents), and contains a message that will be passed to the application's Agent Interaction Diagram, so that each instance of this event can be identified when it appears in the diagram. The Agent Interaction Diagram in discussed in the Tracing and Logging Manual.

String mode – appears in BDIGoalEvents only and identifies the type of JACK Agent Language statement that posted the instance of this goal event (@achieve, @insist, @test or @determine).

2.2.4.4 Event Methods (for MessageEvents only)

Cursor replied()– appears in MessageEvents only, and enables the user to determine whether the agent has received at least one reply to a given message event instance. It returns a triggered cursor, which will test whether the given message event's reply queue is empty. Because the cursor is triggered, it can be used in a @wait_for statement to wait for message event replies to arrive.

MessageEvent getReply() – appears in message events only and allows the user to obtain a reference to each message event that has been returned to the agent as a reply to a given message event instance. To be a reply, a message event must have been sent by the destination agent for the original message, using the reply() method, from within the task that the destination agent was using to handle the original message event.

2.2.4.5 Plan Members

Agent agent – identifies the agent that this plan belongs to. Whenever an instance of a plan is created, this member is assigned a reference to the agent that created the plan instance.


Note: The preferred way to access the agent's methods and members is through the #uses interface statement described in the Plans chapter.

2.2.4.6 Plan Methods

PlanInstanceInfo getInstanceInfo() – a callback that has been supplied so that agents can perform meta-level reasoning about plan instances. It provides a base class for recording information about plan instances. This base class can be extended and accessed in plans that perform meta-level reasoning. For example, one application may extend the PlanInstanceInfo class so that it assigns a precedence rating to each plan instance. This precedence rating may simply be a constant, or it may be calculated in some way. The agent can choose between its available plan instances on the basis of this precedence rating, taking the highest precedence plan it has available as its first choice.

static boolean relevant() – used to determine if a plan is relevant to the actual event. When the agent is looking for a plan to execute in response to an event, it executes the plan's relevant() method to determine whether the given plan is relevant. A plan is relevant if, and only if, it handles the given event and the event's parameters match the pattern specified in the plan's relevant() method. Since events are polymorphic, this can be used to weed out those plans that can handle this event type, but not this particular instance of the event type. Unless the event's parameters satisfy the relevant() method, the agent will deem the plan not relevant to this event.

context() – used to determine if the plan should be executed in the current context. The context specifies a logical condition that must be satisfied if the plan is to be applicable for handling a given event in the current situation. Context often refers to values in an agents knowledge base, which are its beliefs about the state of the world. When the agent needs to handle an event, it looks for a plan instance that is applicable to this event. A plan instance is applicable if it satisfies the plan's context. Typically, the context() method will include logical members in beliefset queries. When an applicable instance of the plan is found, it indicates that the query found a tuple and bound the logical member(s) to its value(s). If there is more than one way to satisfy a context() method's logical expression, there will be multiple instances of the plan that are applicable. One applicable instance will be generated for each set of bindings that satisfy the context() condition.

body() – the plan's main or 'top-level' reasoning method. It describes what it is that the agent actually does when it executes an instance of this plan.

2.2.4.7 BeliefSet Methods

add() – adds new tuples to an agent's private beliefset, or modifies its existing tuples by supplying updated information.

remove() – removes tuples from an agent's beliefset.

public int nFacts() – returns the number of facts (tuples) that are currently held in a given beliefset. For Open World relations, this is the sum of both positive (true) and negative (false) beliefs, while for Closed World relations this is only the number of positive (true) beliefs.

2.2.4.8 Capability Methods

void postEvent(Event e) – the postEvent() method is used to post events within capability code. This method is actually just a convenience method that refers to getAgent().postEvent().

Agent getAgent() – this method is called on a capability instance to return the containing agent.

void autorun() – this method can be overridden in order to provide some initialisation when the capability is actually brought into being.


3 Agents

3.1 Introduction

The Agent class embodies all the functionality associated with a JACK intelligent agent. To define agents, extend this class, adding members and methods that are applicable to the agents current application domain.

3.2 Agent Definition

Agent definitions take the form shown below:

    agent AgentType extends Agent [implements Interface]
    {
       // JACK Agent Language statements specifying containment
       // relationships.
       // These are described in the following sub-sections.
    }

Each component of this definition is explained in the following table:

Syntax Term Description
agent A JACK Agent Language keyword used to introduce an Agent definition.
 AgentType The name of your derived Agent class (which can not be further subclassed).
extends Agent This part of the statement plays the same role as in Java – it indicates that the agent being defined inherits from a JACK Agent Language base class called Agent. The Agent base class implements all the underlying methods that provide an agent's core functionality.
 [implements Interface]  This part of an agent definition is optional.
When present, it states that the agent implements a given Java interface. Java interfaces are like classes that consist of method prototypes without code. When an agent implements an interface, it provides code to implement each of these methods.

Table 3-1: Components of an Agent definition

3.3 Agents and Interfaces

The optional implements Interface component in an agent definition is important when it comes to writing portable JACK Agent Language programs that allow for code re-use. Interfaces provide a common ground between agents that allows them to share plans.

When an agent executes a plan, this plan will often call ordinary Java methods. It is important to remember that when this occurs these methods must be included in the agent definition, not the plan definition. Therefore, any agent that uses this plan must include the defined methods or the plan will not be able to run properly.

This means that the JACK Agent Language places restrictions on which agents can use what plans. So that this restriction can be observed in a modular way, the JACK Agent Language allows these dependencies to be packaged up into a Java Interface. Any agent that wishes to include this plan must declare that it implements this interface. If an Agent class implements the interface, it provides all the methods necessary to run the plan.

3.4 Agent Declarations

An agent should fully describe the functionality it implements via JACK Agent Language definitions. In general, this definition needs to include the following conceptual statements:

These definitions are handled by statements that occur at the field or member level of an agent definition. While there is no restriction on where they appear in Jack code, by convention these definitions appear before the definitions of any regular Java data members and methods that the agent may contain.

An example agent template showing some of the declarations that can appear in an agent appears below:

    agent AgentType extends Agent [implements InterfaceName]
    {

       // Knowledge bases used by the agent are declared here.

       #private data BeliefType belief_name(arg_list);

       // Events handled, posted and sent by the agent are
       // declared here.

       #handles event EventType;
       #posts event EventType reference;
       #sends event EventType reference;

       // Plans used by the agent are declared here.
       // Order is important.

       #uses plan PlanType;

       // Capabilities that the agent has are declared here.

       #has capability CapabilityType reference;

       // other Data Member and Method definitions

    }

Each JACK Agent Language agent declaration is described in more detail in the following sub-sections.

#handles event EventType

This statement identifies the events that the agent will attempt to respond to if they arise. By handling the event, the agent claims to have at least one plan available that it can execute when this event arises. These plans may not be relevant to all forms of the event or applicable in all circumstances, but the agent must know how to handle the event in at least some situations.

Because it is really claiming that the agent's plans can handle the event, the #handles event agent definition statement is analogous to a function prototype. It is an explicit statement with which the runtime can check for completeness rather than functional necessity. However, defining the events that an agent handles up front allows agents to be prototyped and helps ensure that sound design practices are followed.

Including the #handles event definition is also important to ensure that task processing takes place in the agent when the event occurs. If an agent receives an event that it does not handle, a runtime warning is generated and the event is not processed. By claiming to handle the event, the agent looks through its plans to find one that has a matching #handles event statement. A suitable plan might not be found, but at least the agent looks to make sure. Claiming to handle an event is like an employee claiming that a situation falls under their responsibility: they take notice when it occurs and try to do something about it. Whether they succeed or not is another matter.

When an agent definition includes a statement of the following form:

    #handles event EventType;

The agent claims that when an event of EventType occurs, it has a plan to handle it. This plan should be declared with the #uses plan declaration. How this event is processed depends on whether it is a BDI event or a normal event. Behaviour Attribute settings can also influence how events are handled and particularly what happens on plan failure.

Refer to the Events chapter for more details on how different event types are handled and how this behaviour can be customised.

#posts event EventType [reference]

This statement describes an event that the agent can post. Posting an event means that an agent creates an instance of the event and posts it internally (i.e. sends the event to itself).

The #posts event declaration identifies those events that the agent posts explicitly, not those that arise from actions of other agents or indirectly from the agent's own actions or changes in internal state. Therefore, it is usually used to declare that the agent posts events of the types Event, BDIFactEvent and BDIGoalEvent. For more information on these event classes, refer to the Events chapter.

When an agent claims that it posts an event, this event will only arise if it is explicitly generated in one of the agent's methods.

An agent definition contains a statement of this form to indicate that the agent has reasoning methods or code that explicitly causes an event of this type to arise.

Each term in the previous definition is described in the following table:

Term Meaning
#posts event Identifies that the agent can post events of the given type. The event is always posted internally, and hence needs to be handled by the agent's own plans.
 EventType Identifies the type of event to be posted.
 [reference] When present, JACK creates an agent member called  reference which can be used to create events of  EventType using its posting methods.

Table 3-2: Terms in a #posts event declaration

When an agent posts an event, it does so by calling the method postEvent() as shown below:

    postEvent (event)

The event being posted must be constructed using one of the event's posting methods. This is described in the section on posting / sending events in the Events chapter.

Events posted in this way are handled internally by the agent. No other agent is affected by the posting process. Hence, they are like 'thoughts' or 'ideas' that the agent has. The agent essentially tells itself that this event has occurred and needs to be dealt with.

Agents can also send external events to be handled by other agents. These events are called message events and are described in the Events chapter.

#sends event EventType [reference]

This declares that the agent is able to send a message event to another agent. Message events are events that extend either of the following event classes:

For more information on these event classes, refer to the Events chapter.

This declaration identifies events that the agent sends externally. It is analogous to the #posts event statement in all respects other than the fact that the event arises in a different agent to the one that sends it.

When an agent includes a declaration of this type, it indicates that the agent has reasoning methods or code that can send an event of EventType to other agents. The following table describes each term in this definition:

Term Meaning
#sends event This agent has methods or code that can send events to other agents. The event is always sent to a different agent and hence needs to be handled within that agent's own task execution structure.
 EventType Identifies the type of event to be posted.
 [reference] When present, JACK creates an agent member called  reference which can be used to create events of  EventType using its posting methods.

Table 3-3: Terms in a #sends event declaration

When a method belonging to an agent definition needs to send a message event to another agent, it does so by executing the following statement:

    send (agentName, event )

send() is a base method provided by the Agent class. It is almost identical to the postEvent() method except that it takes the name of the target agent as the first argument. This is the full name that the agent is known by on the JACK runtime network. The event being posted must be constructed using one of the event's posting methods. This is described in the section on posting/sending events in the Events chapter.

To obtain the name of an agent, use the Agent base method name(). This method returns the agent's name as a String. Note that the name returned is the full name of the agent which takes the form agent@portal . If a portal name is not supplied, the send() method appends an @ symbol, followed by the portal name of the sending agent. This can cause some ambiguity if there is more than one process in the current application, so it is advisable to always supply the full name of an agent.

#uses plan PlanName

This statement identifies the plans that an agent can execute to handle events. An agent can only execute instances of a plan if it declares that it uses this plan with a #uses plan declaration. If a plan is defined, but no agent uses it, that plan will never be executed.

When an agent definition includes a #uses plan declaration, all instances of this agent that are created have access to the given plan. This plan is said to form part of that agent's plan set.


Note: Ordering of #uses plan statements in the body of an agent (or included capabilities) is important. For normal event handling, plans are tested for relevance and applicability in the order in which they are declared. For BDI event handling, after a candidate plan set is assembled, the plan declared first in the agent will be chosen first in the absence of meta-level reasoning or plan rank being set.

If an agent claims to handle an event, the agent should use a plan that also handles that event. If this is not the case, a warning will be generated when you start up the application. The warning is issued because if an agent has no plan to handle a given event, it cannot strictly claim that it is capable of handling that event.

#has capability CapabilityType reference

The capability concept brings structure to the functional elements of agents. The user declares an agent to have selected capabilities by using the #has capability declaration statement. Each declaration then requires both a capability type name and a reference name that identifies the particular instance of the capability.

If, for instance, Painting is a Capability type, an agent might include the following declaration:

    #has capability Painting painting;

The declaration makes the agent capable of whatever the Painting capability brings, that is, the agent is given access to all of the functional components enclosed by the capability. The reference name painting allows agent code to refer into the capability instance. An agent may have more than one instance of the one capability type.

3.4.1 Beliefsets

3.4.1.1 Conceptual Model

In JACK, beliefs are modelled as beliefset relations which take the following form:

    relationName(key1,key2, ..., data1,data2, ...)

That is, each relation is identified by a name and contains any number of fields. Some of these fields are key fields, uniquely identifying the kind of object that this relation describes, and others are value fields, identifying the attributes of this object that need to be recorded.

Each object described by a beliefset relation is represented as a tuple. A tuple is an instance of the relation where the fields represent the key fields and value fields of a particular object. For example, one may choose to model a bank account with the following beliefset relation:

    bankAccount(account number, name, balance, credit rating)

A particular bank account would then be described as a tuple, such as

    bankAccount(10019875, "Fred Jones", 101.95,"A1");

3.4.1.2 Beliefset Declarations

JACK beliefset declarations within an agent take the following general form;

    #{private|agent|global} data BeliefType belief_name (arg_list)

which declares that a beliefset of type BeliefType is to be contained within the agent. Each declaration is described below.

#private data BeliefType belief_name(arg_list)

When an agent definition includes a statement of this form, it declares a named data that is private to the agent. Agents of this class have private access to the beliefset relation belief_name (or to a user-defined data structure as described in the next section). Private access means that the agent has its own copy of the relation, which it can read and modify independent of all other agents, even those of the same agent class.

Each parameter in the previous definition is described in the following table:

Term Meaning
#private data  A JACK Agent Language field-level construct, which specifies that agents of this class have private access to the beliefset relation.
 BeliefType The type of beliefset relation  that the agent will use. The beliefset type is analogous to the Agent class, and extends one of the underlying JACK Agent Language types.
The beliefset type defines the general properties of the relation such as:
  • the number and type of fields it has;
  • the relation's key; and
  • the relation's query method.
 belief_name Used to identify the instance of the relation that the agent is using.
 arg_list An optional argument. When present, it specifies arguments to be passed to the constructor each time an instance of this beliefset relation is created.
For more information on beliefset constructors and how to use them, see the section entitled BeliefSet Construction.

Table 3-4: Terms in a #private JACK beliefset declaration

When a beliefset relation is private, all the relation's tuples are unique to that agent. If the agent adds or removes tuple information, this is only reflected in its own belief state. Any other agent with access to a relation of the same name will not have its own set of tuples affected. Hence, any changes made to an agent's private relations have no effect on the belief state of other agents.

Private relations are the only beliefset relations where the agent can add, modify or remove tuples: agent and global relations are read-only. It should be noted that:

Refer to the Beliefset Relations chapter for further details.

#agent data BeliefType belief_name(arg_list)

When an agent definition includes a statement of this form, it declares a named data that is shared among all agents of this type in the same process. Agents of this class have agent access to the beliefset relation belief_name (or to a user-defined data structure as described in the next section). Although it is not enforced, agent access means that the agent should have shared read-only access to the relation with other agents of the same class.

Each term from the previous definition is described in the following table:

Term Meaning
#agent data A JACK Agent Language field-level construct, which specifies that agents of this class have shared access to the beliefset relation, but only with other agents of this class.
 BeliefType The type of beliefset relation  that the agent will use. The beliefset type is analogous to the Agent class, and extends one of the underlying JACK Agent Language types.
The beliefset type defines the general properties of the relation such as:
  • the number and type of fields it has;
  • the relation's key; and
  • the relation's query method.
 belief_name Used to identify the instance of the relation that the agent is using.
 arg_list An optional argument. When present, it specifies arguments to be passed to the constructor each time an instance of this beliefset relation  is created.
For more information on beliefset constructors and how to use them, see the section entitled BeliefSet Construction.

Table 3-5: Terms in a #agent beliefset declaration

As access to agent beliefsets is intended to be read-only, the beliefset should be populated by reading data from a file as part of the beliefset constructor. Details on how this can be achieved appear in the BeliefSet Construction section.

The first instance of an agent class that uses an agent beliefset causes the beliefset to be constructed. Each subsequent instance of that agent class is simply allowed access to the beliefset.

An agent can query an agent beliefset using the relation's query method.

Refer to the Beliefset Relations chapter for further details.

#global data BeliefType belief_name(arg_list)

When an agent definition includes a statement of this form, it declares a named data that is shared among all the agents in the same process. This means that all the agents in the process have global access to the beliefset relation belief_name (or to a user defined data structure as described in the next section). Although it is not enforced, global access means that the agent should have shared read-only access to the relation with all other agents in the same process.


Note: A JACK application can consist of one or more processes. However, by default (and unless otherwise specified) an application consists of a single process.

Each term in the previous definition is explained in the following table:

Term Meaning
#global data A JACK Agent Language field-level construct, which specifies that the agent shares this relation with all other agents in the process.
 BeliefType The type of beliefset relation  that the agent will use. The beliefset type is analogous to the Agent class, and extends one of the underlying JACK Agent Language types.
The beliefset type defines the general properties of the relation such as:
  • the number and type of fields it has;
  • the relation's key; and
  • the relation's query method.
 belief_name Used to identify the instance of the relation that the agent is using.
 arg_list An optional argument. When present, it specifies arguments to be passed to the constructor each time an instance of this beliefset relation  is created.

Table 3-6: Terms in a #global beliefset declaration

As access to a global beliefset is intended to be read-only, the beliefset should be populated by reading data from a file as part of the beliefset constructor.

The first instance of an agent class that uses a global beliefset causes the beliefset to be constructed. Each subsequent instance of an agent class that uses the same global beliefset is simply allowed access to the beliefset.

An agent can query a global beliefset using the relation's query methods.

Refer to the Beliefset Relations chapter for further details.

3.4.2 Data stored in User-defined Data Structures

Agent beliefs or normal Java objects can be stored in JACK beliefset relations or in user-defined data structures as agent data members. User-defined data structure members are declared in the agent in an analogous way to JACK beliefset relations by using the #private data, #agent data or #global data statements as described below. The agent's plans gain access to the user-defined data object using the #uses data declaration described in the chapter on plans, and like JACK beliefsets, user-defined data structures can be exported, imported or declared private to capabilities as discussed in the Capabilities chapter.

In addition, a plan can gain access to its enclosing agent as a Java object, (and thus to the agent's data members) by using the #uses interface or the #uses agent implementing statements described in the Plans chapter.

JACK declarations for user-defined data structures within an agent take the following general form:

    #{private|agent|global} data DataType data_name(arg_list)

which declares that a Java object of type DataType is to be contained within the agent. Each declaration is described below:

#private data DataType data_name(arg_list)

When an agent definition includes a statement of this form, it declares a named data that is private to the agent. Agents of this class have private access to data_name.

Private access means that the agent has its own copy of the data object, which it can read and modify independently of all other agents, even those of the same agent class.

Each item in the previous definition is described in the following table:

Term Meaning
#private data Specifies that agents of this class have private access to the data.
 DataType The user-defined data structure.
 data_name The name used to identify the instance of the user-defined data structure that the agent is using.
 arg_list An optional argument. When present, it specifies arguments to be passed to the constructor each time an instance of this data structure is created.

Table 3-7: Terms in a #private user-defined data structure declaration

#agent data DataType data_name(arg_list)

When an agent definition includes a statement of this form, it declares a named data that is shared among all agents of this type in the same process. Agents of this class have agent access to the Java object data_name of type DataType. Although it is not enforced, agent access means that the agent should have shared, read-only access to the data object (data_name) with other agents of the same class.

Each item in the previous definition is described in the following table:

Term Meaning
#agent data Specifies that agents of this class have shared access to the data, but only with agents of the same class.
 DataType The user-defined data structure.
 data_name The name used to identify the instance of the user-defined data structure that the agent is using.
 arg_list An optional argument. When present, it specifies arguments to be passed to the constructor each time an instance of this data structure is created.

Table 3-8: Terms in a #agent user-defined data structure declaration

As access to the object is intended to be read-only, the data object should be initialised when it is constructed. The first instance of an agent class that uses the object will cause the object to be constructed. Each subsequent instance of that agent class is then allowed to access the object.

#global data DataType data_name(arg_list)

When an agent definition includes a statement of this form, it declares a named data that is shared among all agents in the process. Although it is not enforced, global access means that the agent has shared read-only access to the data object data_name with all other agents in the same process.

Each term in the previous definition is described in the following table:

Term Meaning
#global data Specifies that agents of this class have shared access to the data, with all other agents in the process.
 DataType The user-defined data structure.
 data_name The name used to identify the instance of the user-defined data structure that the agent is using.
 arg_list An optional argument. When present, it specifies arguments to be passed to the constructor each time an instance of this data structure is created.

Table 3-9: Terms in a #global user-defined data structure declaration

As access to global data is intended to be read-only, the object should be initialised when it is constructed. The first instance of an agent class that uses the global data object causes the data object to be constructed. Each subsequent instance of an agent class that uses the same global object is allowed to access the data object.