We think of an agent as a small program responsible for interfacing to some resource on behalf of a user or application. We call the corresponding program (or library) responsible for interfacing to the agent on behalf of the application an ‘endpoint’.
Often this agent is running on a remote host and the endpoint is running locally to the service which is using it.
An agent can be this simple:
local agent = require('virgo').agent
# the updates modules adds update-specific behavior
local updates = require('updates')
# provides the ability to configure from the filesystem
local file_config = require('file_config')
return agent([updates, file_config])
Here’s an agent and endpoint in nodejs:
var virgo = require('..');
var agent = virgo.agent;
var endpoint = virgo.endpoint;
var heartbeats = virgo.heartbeats;
endpoint([heartbeats(function(hb) {
process.stdout.write('received hb\n');
process.stdout.write(JSON.stringify(hb, 0, 2) + '\n');
})]).run();
agent([heartbeats()]).run();
Once and for all, let’s solve the problems everyone encounters whenever they build an agent. Come build your agent with us!
The Virgo base agent is written in C with an embedded Luvit runtime.
Many of these features can be discarded. The virgo-example-agent shows the absolute smallest Virgo agent.
Luvit offers an efficient dynamic language with a JIT, great FFI, a friendly C API, and a familiar high-level developer API for asynchronous programming.
Writing cross-platform agents which can be easily and clearly introspected by common debugging tools (such as strace, gdb) is best done in C, but the business logic that an application using agents needs on the agent is often best written in a dynamic language. Dynamic languages are usually greedy for RAM or CPU, are difficult to embed transparently in a C program, or have synchronous models which introduce the complexities of multi-threading into agent applications (often all three). Luajit is incredibly performant, Lua is designed with an easy-to-use C API in mind, and Luvit embeds Libuv so asynchronous Luvit scripts can share a single process with the Libuv event loop.
An open, versioned, easy-to-implement protocol between endpoints and agents enables interoperability. The Virgo protocol consists of messages which are newline-delimited json objects (like json-rpc).