LISP

LISP is a particularly powerful tool for using data from pplapi.com because it is possible to support dynamic agent behavior with LISP. The LISP interface provides access to every pplapi.com field, but the special lisp field specifies a read-eval loop enabling Agents to access their own behavior and potentially store state. It is hypothetically possible to alter the state of other agents, permitting a form of message-passing between Agents.

Please read Security Considerations and Alternatives before deciding to experiment with pplapi.com Lisp Agents.

Booting up an Agent

A small Lisp boot process is required to instantiate an Agent on any given compute resource. For information about installing Lisp, see Common Lisp Pre-requisites.

Create the file boot-random-agent.lisp with the following contents:

(ql:quickload :drakma)
(let
  ((url "http://pplapi.com/random.lisp"))
  (eval (read-from-string (drakma:http-request url)))
  (print (format nil "starting agent ~a" id))
  (eval (read-from-string lisp))
)

Alternately, you can download boot-random-agent.lisp. When this file is evaluated with Common Lisp, a random agent’s behavior loop will begin executing.

sbcl --load boot-random-agent.lisp

The default behavior is to simply check for new behaviors and print the timestamp. To more closely examine an Agent’s behavior, look at the lisp field of any Agent.

The read-eval Loop

The basic read-eval loop contained within Agents may look familiar to those who are familiar with Agent-Based Modeling. It features two function:

  • read-eval, which is responsible for updating the Agent state based on pplapi.com
  • tick, which advances time. Agent behavior may be extended by altering the tick function.

A parameter called memory demonstrates how state may be stored and accessed within the scope of an Agent’s behavior.

(progn
  (defparameter memory "00000000")
  (defun read-eval ()
    (eval (read-from-string
      (drakma:http-request "http://pplapi.com/random.lisp")))
    (eval (read-from-string lisp))
  )
  (defun tick ()
    (sleep 2)
    (print (format nil
      "agent #~a with memory ~a @~a" id memory (get-universal-time)))
    (read-eval)
  )
  (tick)
)

Common Lisp Pre-requisites

pplapi.com is known to work with Common Lisp using the Drakma HTTP library. The suggested Common Lisp implementation is SBCL, but Clozure Common Lisp is known to work as well. The steps in this section will install Steel Bank Common Lisp, QuickLisp, and Drakma.

Step 1: Steel Bank Common Lisp

On OSX, install Steel Bank Common Lisp.

brew install sbcl

On Debian/Ubuntu type Linux systems, installation of SBCL looks like this:

apt-get install sbcl

Step 2: QuickLisp

Install QuickLisp, which is a package manager for Lisp.

curl -O https://beta.quicklisp.org/quicklisp.lisp
sbcl --load quicklisp.lisp --eval "(quicklisp-quickstart:install)"
sbcl --load ~/quicklisp/setup.lisp --eval '(ql:add-to-init-file)'

Step 3: Drakma

Use QuickLisp to install the Drakma Common Lisp HTTP library.

sbcl --eval '(ql:quickload :drakma)'

Step 4: Ready

Now you have Steel Bank Common Lisp, the QuickLisp package manager, and the Drakma HTTP library installed. The pplapi.com examples on this page should now work for you.

Security Considerations

It is recommended to perform LISP experimentation using a firewall and sandbox environment, such as a virtual machine, chroot, or jail. Be aware that once an Agent has booted, it will control its host compute resource, constituting a vector for executing arbitrary commands on your system.

To see how this might be dangerous, consider the following SBCL expression that could be added to an Agent’s tick function:

(run-program "/bin/ls" '() :output *standard-output*)

Although this innocuous example will cause no harm, a malicious payload could obviously cause damage. The run-program function is specific to SBCL - it is not part of the Common Lisp specification - but there are analogous functions for other Common Lisp implementations.

Why would anybody ever run this!?

You might boot an Agent in a Lisp interpreter as a proof of concept. Currently, pplapi.com is read-only, so the Agent code is static and in its current form, it is fairly harmless.

Lisp Sandbox

Work is currently underway to boot an Agent within a Lisp sandbox, which would limit evaluation to a subset of the Lisp language. This would partially mitigate the remote execution risk.

Alternatives

It is far safer and faster to experiment with Agents using an offline Agent-Based Modeling toolkit such as NetLogo or MASON. There are examples for integrating pplapi.com into several ABM toolkits.

Navigation