OAA 1.0 Tutorial


This is intended to be a brief, step-by-step look at what it takes to create an OAA agent. For a more in-depth look, see the OAA Developer's guide.

OAA 1.0 Tutorial


Introduction to OAA

The Open Agent Architecture (OAA) is a multi-agent framework that focuses on enabling more flexible interactions among a dynamic community of heterogeneous software agents. The key idea in OAA is delegation: instead of each agent hard-coding its interactions (method calls or messages), explaining how and who it will interact with, OAA agents express interactions in terms of needs delegated to a Facilitator agent. A Facilitator agent will coordinate the agent community in achieving the task, providing services such as parallelism, failure handling, conflict detection, and so forth that each client agent does not have to worry about itself.

Agents communicate with each other using a logic-based language called the Interagent Communication Language (ICL). Typically, agents use the ICL to register their capabilities with a Facilitator, and then to make requests of the agent community to accomplish tasks, read or write data, and install distributed triggers or monitors.

ICL Syntax

Since all communicate among agents makes use of the Interagent Communication Language, it is important to be able to construct and read ICL messages.

ICL is based on an extension of the Prolog language, and uses Prolog syntax. In Prolog, there are only several element types in the language:

Creating an OAA Agent

Creating an OAA agent is very simple. Every agent must: During the callback functions, an agent may need to make requests of the community to perform tasks, read or write data, or install distributed triggers, and the agent library provides primitives for each of these functions.

Publishing Capabilities (Solvables)

In OAA 1.0, agent capabilities are simply a Prolog-style declaration such as "a(X)". Incoming requests will be unified with the declaration, and if unification succeeds, the request will be forwarded to the agent who published the capability.

Agents may also specify test conditions along with a solvable, written using the operator ':-'. In the following example, an agent will only receive requests where X is bound to an integer less than 10:

(a(X) :- X < 10) 
Note: OAA capabilities declarations are always in the style of a relational declaration, returning solutions in a separate argument, not as a function value. For instance:
// Good 
parent(Child, Parent)

// NOT
Parent = parent(Child).

Defining Capabilities

For each capability declaration defined in an agent's solvable list, the agent must define code to handle the declaration. In OAA 1.0, this declaration is written in a callback named do_event(), which supplies the incoming request and an address ID to the requesting agent. The do_event() callback is expected to perform the function associated with the request and to success, failure, or multiple solutions to the query.

Examples:

 Prolog:

    do_event(_AgentId, a(1)).

 C:
    int do_event(char *AgentId, char *func, char *args, char **answers) {

       int numArgs = list_len(args);
       int processed = TRUE;
       char arg1 = NULL;

       // for solvable:  a(X)
       if ((strcomp(func, "a") == 0) && (numArgs == 1)) {
          NthElt(args, 1, &arg1);
          if (is_var(arg1) || (strcomp(arg1, "1") == 0) {      
             *answers = malloc(BIG_ENOUGH);   // Can use malloc to create space for answer
             sprintf(*answers, "[a(%d)]", 1); // Stores result into answer space
          }
          else *answers = strdup("[]");       // Can use strdup to return result
       }
       else processed = FALSE;                // not returning a result for this query

       return processed;

    }

Tasking the Agent Community

Agents may make requests of the agent community using the built-in primitive solve(). Solve() takes a goal to be executed and a list of control parameters as arguments, and returns success, failure, or multiple solutions for the goal.

In OAA 1.0, the argument list of control parameters may include:

Examples:

   C:       solve("fax_number('Adam Cheyer', FaxNumber)", "[solution_limit(1)]", &answers);

   Prolog:  solve(fax_number('Adam Cheyer', FaxNumber), [solution_limit(1)]).

Data Management

In OAA 1.0, the Facilitator can be used as a blackboard to store data that is shared among the agent communities. Agents write data on the Facilitator using write_bb(Variable, Value), and read it with read_bb(Variable, Value). The Facilitator agent records the source of the data, and if an agent disconnects, all data written by the agent is removed from the Facilitator. If an agent wants to know which agent has written a particular fact, read_bb(AgentId, Variable, Value) may be used.

Example: Prolog: write_bb(name, 'Adam Cheyer').

OAA Triggers

Triggers can be used to monitor communication events (type=event), data changes (type=data), domain-specific tasks (type=test) such as email arriving, webpage changing, and so forth, and if the alarm agent is connected, time (type=alarm).

A trigger must have a type, a recurrence value (when=oneshot, whenever=recurring), a condition and an action. A user may also specify an additional test once the main condition matches, and an OpMask value. The OpMask value is dependent on the trigger type:

OpMasks are not used for time triggers or test triggers.

Examples:


// Agent receives update_data() solvable whenever a new agent
// connects or disconnects to Facilitator (because the agent library
// reads and writes the ksdata() fact on connection/disconnection).
Java: oaa.lib.addRemoteTrigger("data", "whenever",    // Type & recurrence
        "Op", "data(ksdata,D)", "true",               // Condition
        "post_query(update_data(Op,D),[broadcast])"); // Action

// Agent will receive an update_event() message every time
// any agent sends or receives any message (useful for logging).
// Except doesn't log its own messages...
Java: oaa.lib.addRemoteTrigger("event", "whenever",   // Type & recurrence
        "Op", "event(AgentId,Ev)",                    // Condition
        "(AgentId \== " + me.id + ")",                // Additional test
        "post_query(update_event(Op,AgentId,Ev),[broadcast])");

Sample Agents

Here is complete sourcecode to a very simple agent in various programming languages:

Starting a Facilitator Agent

A Facilitator agent must be started before running any other agents, since other agents will connect to the Facilitator to register. To start a Facilitator, run the executable "b". The Facilitor will look for a host and port values on which to start listening -- these values can be specified on the command line, using environment variables, or in a special file called "setup.pl". The Facilitator, if it can correctly start, will print:
./b -oaa_host trestle -oaa_port 3456
 
Loading setup file: '/home/trestle2/cheyer/setup.pl'
  
Listening on trestle port 3456
Ready.
Sometimes under Windows platforms, the Facilitator is extremely picky about how the host is specified, and will sometimes refuse IP numbers or some combinations of DNS names. If this occurs, try using a variable for the host, and seeing if the Facilitator starts. If it does, note the host exactly as it is printed in the "Listening on XXX" message, and record this hostname in the setup.pl file.

Starting an Agent Community

Start-It is an agent which can be used to execute and monitor one or more agents in a community. Start-It reads a configuration file which specifies the list of agents and their parameters. From this, it builds a GUI interface which allows a developer to start and stop individual agents. If an agent dies, Start-it's auto-restart function can be used to automatically restart the agent.

Tracing/Debugging an Agent Community

The Monitor agent is useful for graphically viewing an agent community and for tracing messages being sent among agents. When the Monitor agent is run, it will ask the Facilitator for the list of connected agents and then will display a graphical representation of the community. Clicking on the icon representing an agent will display information about it: its host, programming language, agent library version, and its list of solvables. When the "Record Events" button is pressed, all communication events among agents will be logged and can be viewed, stepped through, or searched by using the Event window.
Copyright 1994-98, SRI International.