Agentopia

Armed with the structural knowledge taken from the docs section, we will now have a little Q&A on how to program with the Agentopia framework. You will see some UML here too; this time, it is sequence diagrams to illustrate how the command flow is.

Q: How do I start a host with a market place?

Have an open port ready (on Linux, probably something greater than 1024 unless you are root), and run the following source code:

final int port = 15907;
Host host = new Host(port);
host.start();

This will open a server socket on port 15907, and create an IMarketPlace automatically, which ticks with a refresh rate of 3 seconds. If you want to control the refresh rate yourself, use the new Host(port, false) constructor to create a market place without timer.

The following UML sequence diagram shows what happens as a cause of the the source code above.

Agentopia setup UML (basic)

Upon start(), which starts a new thread, the Host only calls start() on the market place also if the automatic start flag is set; otherwise, you would need to manually call runStartup(), then repeatedly runTick(), and finally runShutdown() on the IMarketPlace by yourself.

Q: What if I have several network cards (and thus several IP addresses) on my host?

You need to decide which IP or hostname to use. And then you need to tell the host:

final HostId hostId = new HostId("myhostname.com:15907");
Host host = new Host(hostId.getPort());
host.setHomeId(hostId);
host.start();

I agree that it would be better if the network card would not matter. The host itself actually does not care, because it just opens a socket on a port, available from wherever. The agents, on the other hand, have to know the home host to which they jump back (on a remote host, saying "jump me to 127.0.0.1" does not have much effect).

Q: How do I add exits and serviteurs?

To create sustained connections to another Host, you designate a HostId with a hostname or IP and a port. Using this host id, you call createExit() on the market place, which in turn creates a new Sustainer, as shown in the UML diagram below.

Agentopia setup UML (extended)

Creating a serviteur involves instantiating one and adding it to the market place. If the serviteur also implements the IAgentopiaServerRunnable interface, a thread is started on it. This is useful e.g. for regular checks on the file system.

Q: How do I start an agent?

Depends on the agent; here a remote walker agent is started.

IAgentopiaAgent agent = new RemoteWalkerAgent();
host.jumpStart(agent);

Jumpstarting an agent opens a client socket (via a Communicator) to the local Agentopia instance (e.g. "localhost:15907"). The serialized agent (plus subobjects) as well as its class bytecode are loaded into the market place, as shown in the following UML diagram.

Agentopia jumpstart agent UML

On the server socket side, the host tasks a ConnectionInputHandler with processing the transmitted agent, finally adding it to the market place. The de-serialization and dynamic classloading means that from now on, the agent has very limited access rights (no file I/O, no networking) on the host. To exchange stuff, use the treasuring functions on the market place.

Q: How do I actually write my own agent?

Quite easy from the structure, more complex in intent. With the default Agentopia implementation, you need to subclass AbstractAgent and implement two methods: runActivity() and runResults(). Consider the following UML sequence diagram:

Agentopia run agent UML

With a tick of the market place, an AgentExecutionThread runs the agent after supplying a logger and the current market place. The run() method checks the agent state and calls either runActivity() as default, or runResults() when arriving back home after the mission has been finished.

During the activity run, you will mostly use methods in the AbstractAgent superclass; call goExit() to wander to another host, runService() to invoke a serviteur service, and finally goHome() to automatically transfer back home.

In the results run, you will want to bury any results on the home market place by using the buryTreasure() method. Using its heightened access to the market place, your client class can then invoke retrieveTreasureAsHost() on the market (during burying, an MD5 hash of the agent bytecode is taken, and only agents with matching bytecode can retrieve it; as a host, the same restriction does not apply).

Q: Do I have to subclass AbstractAgent?

As long as you plan to use the MarketPlace implementation delivered with Agentopia, the answer is yes. To exchange the market place, subclass Host and override the createMarketPlace() method to return your implementation instead.

Keep in mind that only classes annotated by AgentopiaAgentMarker transmit their class bytecode alongside the serialized object when going through a Sustainer; therefore, a superclass would need to have this marker too.

Your agent still needs to implement the IAgentopiaAgent interface in all cases.

Q: How do I shutdown the system?

Just call shutdown() on the host and wait until all threads have finished (a few seconds should suffice). The UML sequence diagram below shows the shutdown process.

Agentopia shutdown UML

Everything is shut down in a chain reaction. Even agents are expected to react to shutdown() calls by regularly checking whether this method has been called.

Q: Bonus question: How does the Agent GUI work for a specific agent?

The classic MVC (model-view-controller) pattern is followed. There is an AgentopiaSwingController, which creates agents and agent GUIs (defined using the AgentopiaAgentWithGUI annotation on the agent class) on behalf of the application GUI, as shown in the UML sequence diagram below.

Agentopia shutdown UML

In the case above, the AgentStarterPanel creates a TransporterAgent and the accompanying TransporterAgentGui. In the processAgentCreated() method, the agent GUI has the chance to set its appearance before being shown in an AgentInternalFrame within the application GUI. The agent GUI should supply some sort of "Start" button, which initializes the agent with an init(...) method before jump starting it.

Upon returning, an event is fired at the controller, reaching the agent starter panel, which then retrieves or re-creates the agent GUI and calls processAgentReturned(). After retrieving the agent result treasure from the market place, the agent GUI should then supply some sort of "Save" button, which allows saving the results to the local file system.

Q: Any further questions?

This little Agentopia Q&A might have answered the most basic questions, but many more remain open. Over in the author section, you can contact me in case you have a specific question that is not in the list above.

EOF (Aug:2009)