5. Cards

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 type

The 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)

A wind is defined in arvo.hoon as:

++ 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. 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 note), which lull.hoon defines as:

+$ note
$% [%agent [=ship name=term] =task]
[%arvo note-arvo]
[%pyre =tang]
  • An %agent note is a request to another Gall agent, either local or on a remote ship. The ship and name fields are just the target ship and agent name. The task is the request itself, we'll discuss it separately below.
  • An %arvo note is a request to a vane. We'll discuss such requests below.
  • A %pyre note is 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 tang contains an error message.


A task:agent:gall (henceforth just task) is defined in lull.hoon as:

+$ 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 wire/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:


%watch, %watch-as and %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 wire specified at the beginning of the %pass card.
  • %watch-as: This is the same as %watch, except Gall will convert updates to the given mark before delivering them to your agent.
  • %leave: Unsubscribe. The subscription to cancel is determined by the wire at the beginning of the pass card rather than the subscription path, so its argument is just ~.


subscription card examples


Pokes are requests, actions, or just some data which you send to another agent. Unlike subscriptions, these are just one-off messages.

A %poke contains a cage of some data. A cage is a cell of [mark vase]. The mark is just a @tas like %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.

The %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.


poke card examples


A 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.


arvo card examples


[%give gift]

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.

A %give card contains a gift:agent:gall (henceforth just gift), which is defined in lull.hoon as:

+$ 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 or %watch-as request, and %poke-ack is sent in response to a %poke or %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 %watch-ack or %poke-ack gift.


ack card examples


%fact and %kick are both sent out to existing subscribers - entities that have previously %watched a path on your ship.

A %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 %fact. The cage is the data itself - a cell of a mark and a vase.


gift card examples


Here's a diagram that summarizes the different kinds of cards:

card diagram


  • Have a read of the wire and path entries in the type reference.