The Run-Time System consists of the Agent Program and Reticular's run-time agent engine. The Agent Program is a combination of the agent definition in the RADL file and the Project Accessories Library (PAL). The Agent Program is executed by Reticular's run-time agent engine; the combination of the Agent Program and the agent engine produces an executable agent.
At start-up, the Run-Time System initializes the agent engine using information stored in the RADL file and links the required components from the Project Accessories Library. Both the agent definition and the project accessory classes (PACs) are needed: the agent definition supplies the agent with a reasoning capability and an initial mental model; the PACs are the objects used to represent the problem domain and provide the agent the ability to interact with its environment.
The Run-Time System allows an agent to be created in the development environment and then be deployed as a stand-alone entity executing in the run-time environment. It is the agent executing in the Run-Time System that performs useful work. The Run-Time System is distinct from the AgentBuilder Toolkit. After the agent development process is completed, an agent can be executed on any platform with a Java Virtual Machine (version 1.1 or later). The Run-Time System does not require access to the Java Development Environment.
Reticular's agent engine is a proprietary inferencing engine implemented in Java. This engine utilizes an efficient and robust inferencing procedure to match the agent's behavioral rules with the agent's beliefs and incoming messages. The agent engine performs the reasoning defined in the RADL file and executes the specified actions. The available actions are the built-in actions provided by the Run-Time System and the actions based on methods from project accessory classes. The agent engine monitors the execution of the actions and returns execution results to the agent.
There are several ways to launch the agent engine and begin executing an agent program. The Agent Engine Options dialog can be started from the agent tool. The Agent Engine Options dialog can also be started from a shell script, or the agent engine can be started directly from a command line by invoking the engine shell script.
The Agent Engine Options dialog provides a graphical interface for specifying agent engine options. Listed below are the options that can be specified. As the options are specified they are displayed in the text area at the bottom of the dialog. Figure 99 shows the interface.
Figure 99. Agent Engine Options
The RADL file can be specified by clicking on the Add RADL File... button. This will bring up the File dialog in which you can select the RADL file. Multiple RADL files can be specified to run in the same Java Virtual Machine by continuing to click on the Add Radl File... button. To remove a RADL file from the list, select the RADL file name and then click on the Remove RADL File button. Figure 100 shows the Agent Engine Options panel with a RADL file specified.
Figure 100. Agent Engine Options
The CLASSPATH is displayed in a list. It is initialized with the CLASSPATH which was set at the time the Agent Engine Options dialog was opened. You can modify the classpath by using the buttons located below the classpath list. The Add File button will display the File dialog, which will allow you to select either a jar or zip file. The Add Directory button will display the Directory dialog which only allows you to select directories. The Remove button will remove the current selection under the classpath list. The Move Up and Move Down buttons allow you to specify the order the classpath is read. When the Agent Engine is launched, a new Java Virtual Machine will be instantiated using the specified classpath. Note: The classpath field is not editable when the Agent Engine Options dialog is started from the console because the agent will run in the existing Java Virtual Machine and must use the existing classpath.
The Verbose Option s choice box contains the following items: Messages , Changed Beliefs , All Beliefs , Fired Rules , Everything , Trace File... and Clear Verbose Options
Almost any combination of the first five options may be selected. The Changed Beliefs and All Beliefs options are mutually exclusive, so selecting one of them will cause the other to be de-selected. Selecting the Everything option will replace any other options that have been selected. Verbose output will be sent to the output stream used for regular program output (e.g., console or screen) as well as to any trace files that have been specified by the user. Figure 101 shows the Agent Engine Options panel with several verbose options specified.
Figure 101. Agent Engine Options
Shown below are examples of the run-time output for each of the verbose options. These were taken from the BuyerSeller example application. This output will appear in the console or on the screen at run-time and not in the Agent Engine Options dialog. These examples are included here to show the effects of the options selected in the Agent Engine Options dialog.
The Verbose Messages option will cause the engine to print all incoming messages received by the agent during each cycle. All non-empty KQML fields in messages are printed; the content object is printed via the toString method. Figure 102 shows verbose output after the buyer agent has received a message from the Store 2 agent and the message contains a price quote.
Figure 102. Run-Time Output (Verbose Option)
The Changed Beliefs option will cause the engine to print the beliefs which changed during the cycle. Below is an example of the verbose output taken from the BuyerSeller application. Figure 103 shows the changes in the buyer agent's mental model due to a purchase of 2 gallons of milk: the amount the buyer believes is in the account has decreased, and the quantity of milk the buyer believes is in his inventory has increased.
Figure 103. Run-Time Output (Changed Beliefs)
The All Beliefs option will cause the engine to print all beliefs in the agent's mental model at end of cycle. New beliefs or beliefs which changed during the cycle are marked with a *. Figure 104 is an example of the verbose output taken from the Buyer-Seller application at the same cycle used in the previous example. The inventory record for milk and the account balance are marked as new beliefs because they changed during the cycle. The currentTime belief is also marked as a new belief; it's an instance of the built-in Time class which is automatically updated every cycle by the agent engine.
Figure 104. Agent’s Beliefs at End of Cycle
The Fired Rules option will cause the engine to print the names of the rules which fired in the cycle. As you can see in this example, rules may fire more than once per cycle. Here the "Cleanup old quotes" rule fired twice; once per each old price quote that was found in the mental model.
FIRED RULES: Cleanup old quotes, Cleanup old quotes, Receive purchase confirmation, Update account
Selecting the Trace File item will display a File Dialog and a trace file can be selected. Verbose output will also be printed to whatever output stream is being used for program output. A trace file, if one is specified, will contain only the verbose output from a program.
Selecting the Clear Verbose Options item will clear any verbose options that were previously specified. Figure 105 shows the Agent Engine Options dialog after the verbose options have been cleared.
Figure 105. Agent Engine Options
The Program Output choice box contains the following items: Output File... , No Console , No System.out , and Clear Output Options
Program output is all the output generated from the agent engine or from the built-in action SystemOutPrintln , and all output generated by calls to System.out.println in PAC code. Figure 106 shows the Agent Engine Options dialog with an output option specified.
Figure 106. Agent Engine Options
Selecting the Output File item will display a File Dialog and an output file can be selected. Specifying an output file will not affect the standard screen or console output; all output will automatically be printed to the screen or console and the output file(s). Any number of output files can be used. Note that there may be a noticeable slowdown in the agent engine when printing large volumes of data to output files.
Selecting the No Console option will cause the engine to operate without the default console. If you have not also selected the No System.out option, program output will be printed to the standard output stream for your system and to any output files you've specified. If you've selected No Console and No System.out , program output will be printed only to files you've specified. Selecting No System.out without selecting No Console has no effect.
The Error Log Options choice box contains the following items: Error File... , No System.err , and Clear Error.
Error output is all the error messages generated from the agent engine and all output generated by calls to System.err.println in PAC code. Figure 107 shows the Agent Engine Options dialog with an error log option specified.
Figure 107. Agent Engine Options
Selecting the Error File item will display a File Dialog in which an error log file can be selected. Specifying an error log file will not affect the standard screen or console error display; all error messages will automatically be printed to the screen or console and the error log file(s). Any number of error log files can be used.
The No System.err option is similar to the No System.out option: it only has an effect if No Console is also specified. If you've selected No Console and No System.err , error messages will be printed only to any error log files you've specified. Selecting No System.err without selecting No Console has no effect.
Figure 108 shows the options available when starting the agent engine via the shell script. (This is the output that is displayed when invoking the shell script with the help option, i.e., engine -h .) For more explanation, please see the descriptions of the options in Agent Engine Options.
The options that can be specified for the Java Virtual Machine are listed in the following table. For a complete description of these options please see the Java documentation. Numerical option arguments, such as -ss or -mx , should be given with a space between the option name and the number, e.g., -ss 1024.
Figure 108. Agent Engine Command Line Options
The agent engine console provides a standard way to view program output and error messages, as well as control some aspects of agent execution. For some agent applications the standard console will be sufficient for monitoring agent execution; for other applications specialized display panels will be needed. The console can be turned off by specifying the -no-console option on the command line or in the Agent Engine Options Program Output choice box. If the console is not used, all program output and error messages will go to the standard output and error streams (e.g., the screen) and to any files specified by the user. Figure 109 shows the console.
Figure 109. Engine Console
When the console is used it will capture all program output and error messages. The agent engine redirects system output and system errors to the console (and any other files that the user specifies), so all calls to System.out.println or System.err.println in PAC code will be sent to the appropriate console text area. Also, any output generated from the built-in action SystemOutPrintln or other output or error messages from the agent engine will be sent to the console. Capturing PAC output using the console should be acceptable in most situations. However, if you're using the console and need to print some PAC output to the screen instead of the console, code such as the following can be used:
new
PrintWriter(new FileWriter(FileDescriptor.out),
standardOutput.println("yada
yada yada");
This will print to the standard output stream on your system, NOT to the console. Similarly, building a PrintWriter from FileDescriptor.err will allow you to print to the standard error stream on your system. Of course the name of the PrintWriter object (here, " standardOutput ") can be any name you choose. The second argument in the constructor, " true ", tells the system to flush the output buffer automatically after every println statement; use this value if you want output to appear immediately after it's printed. To use this code your PAC will need the import statement import java.io.*; (or you could import each of the classes separately or use the full package.class names such as j ava.io.PrintWriter ).
The main purpose of the console is to display program output. The console features a scrollable text area and three buttons that affect the output display: Save , Clear , and Freeze . Clicking on the Save button will cause a File Dialog to appear; all the output currently in the output text area (including any text that has scrolled out of view) will be saved into the selected file. Clicking on the Clear button will clear the output text area. Clicking on the Freeze button will change the button label to Resume and will freeze the output but will NOT halt the agent engine. The engine will continue executing normally and all output will be stored in the console until the Resume button is clicked, then all the stored output will be written to the output text area. The Freeze button is provided to make it easier to view a running agent without distraction from frequent updates in the output text area. Figure 110 shows the Save Output File dialog used to select a file for the console's program output.
Figure 110. Save File Dialog
The console has a scrollable error text area located below the output text area. This area includes two buttons-- Save and Clear-- that affect the error display. These buttons have the same effect as the buttons for the output text area, except that they save or clear the error text area. There is no Freeze button for the error display since error messages will be infrequent and freezing the display is unnecessary.
The File menu in the console offers the following items and their keyboard shortcuts: Load RADL File... , Close Console , Exit Run-Time System. The control key equivalents for each of these File menu selections are shown in the following table.
Selecting the Load RADL File... item will cause a File Dialog to be displayed. If a file is selected, the current agent engine will be destroyed and a new agent engine will be started using the newly selected RADL file and whatever options were used in the previous agent engine.
Selecting the Close Console item will close the console but leaves the agent engine runnin g . Output and error messages from the agent engine and PACs will continue to be printed to files if any files were specified by the user.
Selecting the Exit Run-Time System item will terminate the agent engine and close the console.
The Edit menu in the console provides the following commands: Cut , Copy , and Paste . The keyboard shortcuts for these menu items are shown in the following table.
All Edit options are applied to a highlighted block of text in either the output or error text areas. (Currently not functional)
The Exec menu provides the following commands: Set Engine Options... , Restart Engine , Terminate Engine . The control key equivalents for each of these Exec menu selections are shown in the following table.
Selecting the Set Engine Options... item will cause the Agent Engine Options dialog to be displayed. This allows the user to select a new RADL file and/or new options for the agent engine. If the user clicks the OK button the current agent engine will be destroyed and a new agent engine will be started using the RADL file and options specified in the Agent Engine Options panel.
Selecting the Restart Engine item will destroy the current agent engine and start a new agent engine using the current RADL file and options. Any PAC control panels subclassed from java.awt.Window or its subclasses (e.g., java.awt.Frame , java.awt.Dialog ) will be destroyed.
Selecting the Terminate Engine item will destroy the current agent engine. Any PAC control panels subclassed from java.awt.Window or its subclasses (e.g., java.awt.Frame, java.awt.Dialog ) will be destroyed. Terminating the agent engine will not close the console.
When more than one agent is running in the same Java Virtual Machine, the MultiAgent console will be used, see Figure 111. In addition to the regular Agent Engine Console you get for each agent running, you will also see a MultiAgent Engine Console. The MultiAgent Engine Console has a similar interface to the Agent Engine Console, but behaves differently. The output you see on the output text area of the MultiAgent Engine Console includes the RADL files and options used to start the engines for the agents. Also, if any output/error messages cannot be redirected to the proper Agent Engine Console, it will be displayed on the MultiAgent Engine Console.
Figure 111. Multi-Agent Engine Console
The console provides a scrollable text area and two buttons that affect the ouput display: Save and Clear . These buttons perform the same functions as the Save and Clear buttons for the Agent Engine Console. The Save button saves the output to a file, and the Clear button clears the output text area. The second scrollable text area is for error output. This area also includes two buttons: Save and Clear . These buttons have the same effect as the buttons for the output text area, except that they save and clear the error text area.
The File menu in the console offers the following items: Close and Exit . The Close button will close the MultiAgent Engine display and leave running any agent engines that are currently executing. If the MultiAgent Engine Console is the only window open, this will exit the virtual machine. If the Exit menu item is selected, the console will terminate all agent engines and exit the virtual machine.
The Exec menu provides commands to Restart All Engines and Terminate All Engines . Selecting Restart All Engines will terminate all agent engines running in this Java Virtual Machine and restart them using the current RADL file and options. Selecting the Terminate All Engines menu item will terminate all agent engines running in this Java Virtual Machine.
The agent engine provides a suite of built-in actions which can be called from rules. This section describes the actions and the required arguments.
void ConnectAction( String actionName, Object pacObject )
(DO ConnectAction( [VAL String "action1"], [INST MyPac<pac1>] ))
ConnectAction provides a way to connect a named action to its underlying PAC object. This is not required in AgentBuilder 1.1 and later and exists only for compatibility with older RADL code.
(DO [RVAR Float<currentCycleTime>] = GetCycleTime())
GetCycleTime returns the current value for the agent engine cycle length, in seconds. The Float value returned by the action can be stored into a variable and then asserted into the agent's mental model or used elsewhere on the RHS of the enclosing rule.
(DO [RVAR String<hostAddress>] = GetHostAddress())
GetHostAddress returns the IP address (as a String , e.g., "199.106.0.42") of the physical machine on which the agent engine is running. The String value returned by the action can be stored into a variable and then asserted into the agent's mental model or used elsewhere on the RHS of the enclosing rule.
(DO [RVAR String<hostName>] = GetHostName())
GetHostName returns the host name of the physical machine on which the agent engine is running. The String value returned by the action can be stored into a variable and then asserted into the agent's mental model or used elsewhere on the RHS of the enclosing rule.
String GetSystemProperty( String keyString )
(DO [RVAR String<cwd>] = GetSystemProperty( [VAL String "user.dir"] ))
GetSystemProperty provides access to the standard system properties that are available to any Java program. GetSystemProperty is implemented via the standard System.getProperty(String) method and uses the same key strings, e.g., " user.dir ". The String value returned by the action can be stored into a variable and then asserted into the agent's mental model or used elsewhere on the RHS of the enclosing rule.
The OpenConsole built-in action is intended for use in environments where the engine is running without a console and a situation is detected which should be brought to the attention of the user. If there is no console at the time OpenConsole is invoked it will open a console and begin printing program output and error messages to the console (in addition to any output or error log files that may be open). If OpenConsole is invoked when a console is already open then the action will have no effect.
void OpenInputDialog( String dialogName,
String promptString, Class expectedType )
( DO OpenInputDialog( [VAL String "Price Dialog"]
[VAL String "Enter the maximum acceptable price"]
The OpenInputDialog built-in action provides easy access to the InputDialog built-in PAC. Although it is possible to build and use the InputDialog directly, this built-in action simplifies the construction. The InputDialog can be used to obtain input of class String , Character , Boolean , or any of the numerical classes (e.g., Integer ). For each dialog the user must provide a reference to the agent's AgentInfo object, a name for the input dialog, a prompt string, and the expected type (as a java.lang.Class object). The dialog will only accept input that can be converted to the specified type, so for example an InputDialog that expects a Float input will not accept an input string containing non-numeric characters. Any range checking or further testing of the input must be done by the agent. Figure 112 shows the InputDialog built by the OpenInputDialog action shown above.
Figure 112. Built-In Input Dialog
In the example shown above the dialog will be named Price Dialog , the prompt string will be E nter the maximum acceptable price , and the dialog will only accept a Float input. The InputDialog will be a modal dialog which will be displayed until the user types a valid input and hits the Enter key on the keyboard or clicks on the OK button or the Cancel button. If the input cannot be converted into the specified type an error dialog will be displayed. Figure 113 shows the error dialog for this example.
Figure 113. Error Dialog
If the user enters a valid input, the input object (in this case a Float object) will be sent to the agent as the content of a KQML message with the performative "tell". The following patterns could be used in a rule to detect a message from the InputDialog built in the OpenInputDialog example above:
(OBJ [VAR KqmlMessage<%m>.Sender] EQUALS [VAL String "Price Dialog"]) (OBJ [VAR KqmlMessage<%m>.Performative] EQUALS [VAL String "tell"]) (OBJ [VAR KqmlMessage<%m>.ContentType] EQUALS [VAL Class Float])
If a KQML message satisfies these patterns then the message will be accepted as an input message from the InputDialog and the value can be extracted from the content object and stored into the agent's mental model.
void OpenOutputDialog( String outputString )
(DO OpenOutputDialog( [VAL String "The answer is 42."] )
OpenOutputDialog creates a simple output dialog with a text area and displays the given output string in the text area.
void RegisterAgent( AgentInfo otherAgentInfo )
(DO RegisterAgent( [VAR AgentInfo<?info>] ))
The RegisterAgent built-in action is used to register a new agent with the communication system.
void RemoveRule( String ruleName )
(DO RemoveRule( [VAL String "Rule 1"] ))
RemoveRule removes the specified rule from the agent's rule base.
void SendKqmlMessage( KqmlMessage outputMessage,
(DO SendKqmlMessage( [NEW KqmlMessage],
RECEIVER[ VAR Store<?s>.Name ],
PERFORMATIVE[ VAL String "achieve" ],
REPLY_WITH[ VAL String "Purchase Confirmation" ],
SendKqmlMessage fills in the fields of the outboundMessage argument with any values specified in the remainder of the argument list then queues the message for sending at the end of the cycle. This action will not modify the fields in the outbound message if the corresponding argument is unspecified. For example, if the content argument is not specified, the content field in the outbound message will not be changed. This allows for easy re-use of message objects without requiring a complete rebuilding of the message. The outboundMessage argument may be a reference to a new or existing KQML message object.
In the example shown (from buyer.radl ) a new KQML message object is used as the first argument. The message will be initialized with the agent's name as the sender, a store's name as the receiver, the performative "achieve" and "Purchase confirmation" as the string with which to reply. These values are determined by a communications protocol developed when the system was designed; the buyer agent and the seller agents have rules that were written according to this protocol. For the fourth argument a variable of type Purchase will be installed as the content object in the outbound message. The other fields (i nReplyTo, language , ontology , protocol , toAgentName , and fromAgentName ) will be left as-is in the outbound message, which in this case means they will be null.
void SetCycleTime( float cycleTimeInSeconds )
(DO SetCycleTime( [VAL Float 3.0] ))
SetCycleTime changes the length of the agent engine cycle to the specified value. The input value must be given in seconds.
void Sleep( int numberOfSeconds )
(DO Sleep( [VAL Integer 30] ))
The Sleep built-in action will put the agent to sleep for a specified amount of time, starting at the end of the cycle in which the action is invoked. The agent engine will monitor its incoming message queue and wake the agent when a message has been received, even if the specified sleep time has not elapsed. If no messages are received, the engine will wake the agent when the specified sleep time has elapsed.
The SleepUntilMessage built-in action will put the agent to sleep for an unspecified amount of time, starting at the end of the cycle in which the action is invoked. The agent engine will monitor its incoming message queue and wake the agent when a message has been received.
The SleepWhenIdle built-in action will put the agent to sleep for an unspecified amount of time, starting at the end of the next cycle in which no rules are fired. The sleep may start as soon as the next cycle following the cycle in which SleepWhenIdle was invoked, or the start of the sleep may be delayed indefinitely. The agent engine will monitor its incoming message queue and wake the agent when a message has been received.
This action is useful in situations where the agent must complete some processing, possibly over several cycles, before going to sleep.
(DO SystemOutPrintln( [VAL String "yada yada yada"] ))
SystemOutPrintln provides a mechanism for printing output from within a rule. Note that the argument must be a string. Printing any other data type requires that it be converted into a string before SystemOutPrintln is invoked.
There are several reasons why a KQML message might not be delivered. We'll explain some of these and provide a method for detecting and handling them.
The first reason that a message might fail to be delivered is that the sending agent doesn't have communication information about the receiving agent; i.e., the receiving agent is not registered with the sending agent. When this occurs, an error message will be printed and the KQML message will be asserted into the agent's mental state. The following error message results from attempting to send a message to an agent that is not registered with the sending agent.
ERROR Unknown receiver agent "TestAgent"
If the communication information is unknown, there are two alternative methods for adding the agent communication information. The easiest solution is to include all of the agents (that need to communicate) in the same agency. The second solution is to construct an AgentInfo object containing the receiving agent's communication information and use the built-in action, RegisterAgent, to register the receiving agent with the sending agent.
A message might also fail to be delivered if the receiving agent is not currently executing (i.e. the agent is off-line). This kind of event generates a warning message and, like the previous failure, the KQML message is asserted into the agent's mental state. The following warning message is generated when sending a message to an agent that is off-line.
WARNING: Unable to send message to agent "KqmlMessageAgent"
In either case described above, the user is responsible for handling these types of message failures. Whenever a message fails to be delivered a flag in the KQML message is set. This flag can be obtained by calling the message's getSendError method. The following rule is an example of how to handle message send failures:
( "Receive Undelivered Messages"
( OBJ [ VAR KqmlMessage<%message>] getSendError ( ) )
( DO SystemOutPrintln ( [ SFUNC Concat(
[ VAL String "Unable to Deliver Message To: " ]
[ VAR KqmlMessage<%message>.receiver] )
( RETRACT ( [ VAR KqmlMessage<%message>] ) )
The mental conditions of this rule will be met when a KQML Message's getSendError method returns true. When this is the case, the engine will execute the RHS elements of this rule. First, it will print a message indicating that a KQML message was undelivered. Next, it will remove the KQML message from the agent's mental state.
You need to keep in mind that in most cases, the KQML Message send routine will not return in the next cycle of the engine. That is, it could take the engine from 2 to 4 engine cycles to determine that a KQML message is not deliverable.
The agent engine operates on a fixed-time-length cycle. During each cycle the agent engine:
If the engine finishes processing before the time allotted for the cycle the engine automatically goes to sleep until the start of the next cycle. Approximately one-half of the engine cycle is intended for pattern matching and updating the mental model, and the other half is intended for executing actions.
On the other hand, if the engine does not finish processing before the end of the allowed time, the cycle simply continues past its allowed time. Currently there is no mechanism in place for warning the user about over-long processing, but later versions will notify the user when the pattern matching or action execution cannot be completed in the allotted time. Overrunning the cycle boundary is not usually a problem, except that it may shift the starting time of a later cycle and delay the execution of a committed action.
It's expected that separate threads will be used for all long-running actions. Any invocation of a run() method will automatically be executed on its own thread. All regular actions, i.e., the actions that will execute on the common execution thread, are expected to execute quickly (in comparison to the cycle length). If long-running actions are executed on the regular execution thread they may cause a delay of several agent cycles.
Thread priorities. Currently the agent engine main thread and regular action execution threads run at priority 4; this value is used because it is 1 less than the Java Event-handler thread. Any separately-threaded actions run at priority 3 so that they will not preempt the engine thread. Currently there is no mechanism that allows the agent programmer to change the priorities of the engine thread or the action threads.
Although separately threaded actions will help avoid delays in the engine cycle, they must be used with care. It's the responsibility of the agent programmer to synchronize any interactions between the separately threaded action and the rest of the agent engine. In particular, control panel PACs must synchronize access to any data structures which are used by methods called from the agent engine and also called from event handler code.
For example, assume that some PAC has a print(String) method that prints to a text area. Assume also that the PAC has an event handler for a button that prints a message to the same text area whenever the user clicks on the button. If access to the text area is not synchronized (via synchronized methods or synchronized blocks of code) the output from the agent engine and the output from the PAC may be intermixed. In this example the print method could be executing on the engine's execution thread when the user clicks the button. Then the PAC's event handler code would execute on the event handler thread, interrupting the regular print method. Finally, after the event handler code has finished printing its message into the text area, the remainder of the original print argument would be printed. This synchronization failure would only cause confusing output; in other situations, synchronization failures could cause the program to crash or return incorrect results.