As we previously discussed, most arms of an agent core produce a cell of
[effects new-agent-core], and the type we use for this is typically
(quip card _this). We've covered
_this, but we haven't yet looked at
card effects in detail. That's what we'll do here. In explaining
cards we'll touch on some concepts relating to the mechanics of pokes, subscriptions and other things we've not yet covered. Don't worry if you don't understand how it all fits together yet, we just want to give you a basic idea of
cards so we can then dig into how they work in practice.
card:agent:gall type (henceforth just
card) has a slightly complex structure, so we'll walk through it step-by-step.
lull.hoon defines a
card like so:
+$ card (wind note gift)
wind is defined in
++ wind|$ [a b]$% [%pass p=wire q=a][%slip p=a][%give p=b]==
Gall will not accept a
%slip, so we can ignore that. A
card, then, is one of:
[%pass wire note][%give gift]
We'll consider each separately.
[%pass wire note]
The purpose of a
%pass card is to send some kind of one-off request, action, task, or what have you, to another agent or vane. A
%pass card is a request your agent initiates. This is in contrast to a
%give card, which is sent in response to another agent or vane.
The type of the first field in a
%pass card is a
wire is just a list of
@ta, with a syntax of
/foo/bar/baz. When you
%pass something to an agent or vane, the response will come back on the
wire you specify here. Your agent can then check the
wire and maybe do different things depending on its content. The
wire type is covered in the types reference. We'll show how
wires are practically used later on.
The type of the next field is a
note:agent:gall (henceforth just
lull.hoon defines as:
+$ note$% [%agent [=ship name=term] =task][%arvo note-arvo][%pyre =tang]==
noteis a request to another Gall agent, either local or on a remote ship. The
namefields are just the target ship and agent name. The
taskis the request itself, we'll discuss it separately below.
noteis a request to a vane. We'll discuss such requests below.
noteis used to abort an event. It's mostly used internally by
kiln(a submodule of
%hood), it's unlikely you'd use it in your own agent. The
tangcontains an error message.
task:agent:gall (henceforth just
task) is defined in
+$ task$% [%watch =path][%watch-as =mark =path][%leave ~][%poke =cage][%poke-as =mark =cage]==
Note a few of these include a
path field. The
path type is exactly the same as a
wire - a list of
@ta with a syntax of
/foo/bar/baz. The reason for the
path distinction is just to indicate their separate purposes. While a
wire is for responses, a
path is for requests. The
path type is also covered in the types reference.
The kinds of
tasks can be divided into two categories:
%leave all pertain to subscriptions.
%watch: A request to subscribe to the specified
path. Once subscribed, your agent will receive any updates the other agent sends out on that
path. You can subscribe more than once to the same
path, but each subscription must have a separate
wirespecified at the beginning of the
%watch-as: This is the same as
%watch, except Gall will convert updates to the given
markbefore delivering them to your agent.
%leave: Unsubscribe. The subscription to cancel is determined by the
wireat the beginning of the
passcard rather than the subscription
path, so its argument is just
Pokes are requests, actions, or just some data which you send to another agent. Unlike subscriptions, these are just one-off messages.
%poke contains a
cage of some data. A
cage is a cell of
[mark vase]. The
mark is just a
%foo, and corresponds to a mark file in the
/mar directory. We'll cover
marks in greater detail later. The
vase contains the actual data you're sending.
%poke-as task is the same as
%poke except Gall will convert the
mark in the
cage to the
mark you specify before sending it off.
note-arvo is defined in
lull.hoon like so:
+$ note-arvo$~ [%b %wake ~]$% [%a task:ames][%b task:behn][%c task:clay][%d task:dill][%e task:eyre][%g task:gall][%i task:iris][%j task:jael][%k task:khan][%$ %whiz ~][@tas %meta vase]==
The letter at the beginning corresponds to the vane -
%b for Behn,
%c for Clay, etc. After the vane letter comes the task. Each vane has an API with a set of tasks that it will accept, and are defined in each vane's section of
lull.hoon. Each vane's tasks are documented on the API Reference page of its section in the Arvo documentation.
The purpose of a
%give card is to respond to a request made by another agent or vane. More specifically, it's either for acknowledging a request, or for sending out updates to subscribers. This is in contrast to a
%pass card, which is essentially unsolicited.
%give card contains a
gift:agent:gall (henceforth just
gift), which is defined in
+$ gift$% [%fact paths=(list path) =cage][%kick paths=(list path) ship=(unit ship)][%watch-ack p=(unit tang)][%poke-ack p=(unit tang)]==
These can be divided into two categories:
%watch-ack is sent in response to a
%watch-as request, and
%poke-ack is sent in response to a
%poke-as request. If the
(unit tang) is null, it's an ack - a positive acknowledgement. If the
(unit tang) is non-null, it's a nack - a negative acknowledgement, and the
tang contains an error message. Gall automatically sends a nack with a stack trace if your agent crashes while processing the request, and automatically sends an ack if it does not. Therefore, you would not explicitly produce a
%kick are both sent out to existing subscribers - entities that have previously
%watched a path on your ship.
%kick gift takes a list of subscription
paths and a
(unit ship), which is the ship to kick from those paths. If the
unit is null, all subscribers are kicked from the specified paths. Note that sometimes Gall can produce
%kick gifts without your agent explicitly sending a card, due to networking conditions.
%facts are how updates are sent out to subscribers. The
paths field is a list of subscription paths - all subscribers of the specified
paths will receive the
cage is the data itself - a cell of a
mark and a
Here's a diagram that summarizes the different kinds of