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.
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 basic read-eval loop contained within Agents may look familiar to those who are familiar with Agent-Based Modeling. It features two 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)
)
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.
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
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)'
Use QuickLisp to install the Drakma Common Lisp HTTP library.
sbcl --eval '(ql:quickload :drakma)'
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.
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.
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.
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.