on master help sign in
Add new gall guide.
1193eeeTinnus Napbus
content/docs/userspace/_index.md+1−1
@@ -12,7 +12,7 @@ Urbit's userspace is managed by Arvo's Gall vane.
12
12
13An overview of userspace in Urbit.
13An overview of userspace in Urbit.
14
14
15−## [Gall Guide](/docs/userspace/gall-guide)
15+## [Gall Guide](/docs/userspace/gall-guide/intro)
16
16
17Learn how to develop Gall agents.
17Learn how to develop Gall agents.
18
18
content/docs/userspace/gall-guide.mddeleted−14
@@ -1,14 +0,0 @@
1−+++
2−title = "Gall Guide"
3−weight = 5
4−template = "doc.html"
5−+++
6−
7−[**The Complete Guide to Gall and Userspace Apps on
8−Urbit**](https://github.com/timlucmiptev/gall-guide), or more colloquially
9−referred to as just "the Gall Guide," was contributed by a member of our
10−community named `~timluc-miptev`.
11−
12−Our plan is ultimately to make this part of the official documentation found
13−here, but for now, know that it has our official seal of approval and is
14−actively maintained.
content/docs/userspace/gall-guide/1-arvo.mdnew file+298
@@ -0,0 +1,298 @@
1++++
2+title = "1. Prologue"
3+weight = 5
4+template = "doc.html"
5++++
6+
7+This document is a prologue to the Gall guide. If you've worked though [Hoon
8+School](/docs/hoon/hoon-school/intro) (or have otherwise learned the basics of
9+hoon), you'll likely be familiar with generators, but not with all the other
10+parts of the Arvo operating system or the way it fits together. We'll go over
11+the basic details here so you're better oriented to learn Gall agent
12+development. We'll not go into the internal workings of the kernel much, but
13+just what is necessary to understand it from the perspective of userspace.
14+
15+## Arvo and its Vanes
16+
17+[Arvo](/docs/arvo/overview) is the Urbit OS and kernel which is written in
18+[Hoon](/docs/glossary/hoon), compiled to [Nock](/docs/gossary/nock), and
19+executed by the runtime environment and virtual machine
20+[Vere](/docs/glossary/vere). Arvo has eight kernel modules called vanes:
21+[Ames](/docs/arvo/ames/ames), [Behn](/docs/arvo/behn/behn),
22+[Clay](/docs/arvo/clay/clay), [Dill](/docs/arvo/dill/dill),
23+[Eyre](/docs/arvo/eyre/eyre), [Gall](/docs/arvo/gall/gall),
24+[Iris](/docs/arvo/iris/iris), and [Jael](/docs/arvo/jael/jael).
25+
26+Arvo itself has its own small codebase in `/sys/arvo.hoon` which primarily
27+implements the transition function `(State, Event) -> (State, Effects)` for
28+events injected by the runtime. It also handles inter-vane messaging, the
29+[scry](/docs/arvo/concepts/scry) system, and a couple of other things. Most of
30+the heavy lifting is done by the vanes themselves - Arvo itself typically just
31+routes events to the relevant vanes.
32+
33+Each vane has its own state. Gall's state contains the agents it's managing,
34+Clay's state contains all the desks and their files, Jael's state contains all
35+its PKI data, etc. All the vanes and their states live in Arvo's state, so
36+Arvo's state ultimately contains the entire OS and its data.
37+
38+Here's a brief summary of each of the vanes:
39+
40+- **Ames**: This is both the name of Urbit's networking protocol, as well as the
41+ vane that handles communications over it. All inter-ship communications are
42+ done with Ames, but you'd not typically deal with it directly in a Gall agent
43+ because Gall itself handles it for you.
44+- **Behn**: A simple timer vane. Behn lets your Gall agent set timers which go off
45+ at the time specified and notify your agent.
46+- **Clay**: Filesystem vane. Clay is a revision-controlled, typed filesystem with a
47+ built-in build system. Your agent's source code lives in Clay. Your agent's
48+ source code and relevant files are automatically built and loaded upon
49+ installation, so your Gall agent itself would not need to interact with Clay
50+ unless you specifically wanted to read and write files.
51+
52+- **Dill**: Terminal driver vane. You would not typically interact with Dill
53+ directly; printing messages to the terminal is usually done with hinting runes
54+ and functions rather than tasks to Dill, and CLI apps are mediated by a
55+ sub-module of the Hood system agent called Drum. CLI apps will not be touched
56+ on in this guide, but there's a separate [CLI
57+ Apps](/docs/hoon/guides/cli-tutorial) guide which covers them if you're
58+ interested.
59+- **Eyre**: Webserver vane. App front-ends are served via Eyre. It's possible to
60+ handle HTTP requests directly in a Gall agent (see the [Eyre
61+ Guide](/docs/arvo/eyre/guide) for details), but usually you'd just serve a
62+ front-end [glob](/docs/userspace/dist/glob) via the `%docket` agent, so you'd
63+ not typically have your agent deal with Eyre directly.
64+
65+- **Gall**: App management vane; this is where you agent lives.
66+
67+- **Iris**: Web client vane. If you want your agent to query external web APIs and
68+ the like, it's done via Iris. Oftentimes web API interactions are
69+ spun out into [Threads](/docs/userspace/threads/overview) to avoid
70+ complicating the Gall agent itself, so a Gall agent would not necessary deal
71+ with Iris directly, even if it made use of external APIs.
72+- **Jael**: Key infrastructure vane. Jael keeps track of PKI data for your ship and
73+ other ships on the network. Jael's data is most heavily used by Ames, and
74+ since Gall handles Ames communications for you, you'd not typically deal with
75+ Jael directly unless your were specifically writing something that made use of
76+ its data.
77+
78+## Userspace
79+
80+Gall agents live in "userspace" as opposed to "kernelspace". Kernelspace is Arvo
81+and its eight vanes. Userspace is primarily Gall agents, generators, threads,
82+front-ends, and all of their related files in Clay. The distinction looks
83+something like this:
84+
85+[![kernelspace/userspace diagram](https://m.tinnus-napbus.xyz/pub/gall/kernelspace-userspace-diagram.svg)](https://m.tinnus-napbus.xyz/pub/gall/kernelspace-userspace-diagram.svg)
86+
87+By and large, Gall _is_ the userspace vane - the majority of userspace is either
88+Gall agents, or things used by Gall agents. Apart from the agents themselves,
89+there's also:
90+
91+- **Generators**: These are basically scripts. You'll likely already be familiar
92+ with these from Hoon School. Aside from learning exercises, their main use is
93+ to make interacting with Gall agents easier from the dojo. Rather than having
94+ to manually craft `%poke`s to agents, generators can take a simpler input,
95+ reformat it into what the agent actually expects, and poke the agent with it.
96+ When you do something like `:dojo|wipe` in the dojo, you're actually running
97+ the `/gen/dojo/wipe.hoon` generator and poking the `%dojo` agent with its
98+ output.
99+- **Threads**: These are kind of like mini transient Gall agents, and are managed by
100+ the `%spider` agent. They can be used as mere scripts like generators, but
101+ their main purpose is for performing complex IO. For example, suppose you need
102+ to query some external web API, then with the data in its response you make
103+ another API call, and then another, before finally having the data you need.
104+ If one of the API calls fails, your Gall agent is potentially left in a
105+ strange intermediary state. Instead, you can put all the IO logic in a
106+ separate thread which is completely atomic. That way the Gall agent only has
107+ to deal with the two conditions of success or failure. Writing threads are
108+ covered in a [separate guide](/docs/userspace/threads/basics/fundamentals),
109+ which you might like to work through after completing the Gall Guide.
110+
111+- **Front-end**: Web UIs. It's possible for Gall agents to handle HTTP requests
112+ directly and dynamically produce responses, but it's more typical to have a
113+ separate [glob](/docs/userspace/dist/glob) of HTML, CSS, Javascript, images,
114+ etc, which are served to the client like an ordinary web app. Such front-end
115+ files are typically managed by the `%docket` agent which serves them via Eyre.
116+ The [software distribution guide](/docs/userspace/dist/guide) covers this in
117+ detail, and you might like to work through it after completing the Gall Guide.
118+
119+## The Filesystem
120+
121+On an ordinary OS, you have persistent disk storage and volatile memory. An
122+application is launched by reading an executable file on disk, loading it into
123+memory and running it. The application will maybe read some more files from
124+disk, deserialize them into data structures in memory, perform some computations
125+and manipulate the data, then serialize the new data and write it back to disk.
126+This process is necessary because persistent storage is too slow to operate on
127+directly and the fast memory is wiped when it loses power. The result is that
128+all non-emphemeral data is ultimately stored as files in the filesystem on disk.
129+Arvo on the other hand is completely different.
130+
131+Arvo has no concept of volatile memory - its whole state is assumed to be
132+persistent. This means it's unnecessary for a Gall agent to write its data to
133+the filesystem or read it in from the filesystem - an agent can just modify its
134+state in situ and leave it there. The urbit runtime writes events to disk and
135+backs up Arvo's state on the host OS to ensure data integrity but Arvo itself
136+isn't concerned with such details.
137+
138+The result of this total persistence is that the filesystem—Clay—does not have
139+the same fundamental role as on an ordinary OS. In Arvo, very little of its data
140+is actually stored in Clay. The vast majority is just in the state of Gall
141+agents and vanes. For example, none of the chat messages, notebooks, etc, in the
142+Groups app exist in Clay - they're all in the state of the `%graph-store` agent.
143+For the most part, Clay just stores source code.
144+
145+Clay has a few unique features - it's a typed filesystem, with all file types
146+defined in `mark` files. It's revision controlled, in a similar way to git. It
147+also has a built-in build system (formerly a separate vane called Ford, but was
148+merged with Clay in 2020 to make atomicity of upgrades easier). We'll look at
149+some of these features in more detail later in the guide.
150+
151+## Desk Anatomy
152+
153+The fundamental unit in Clay is a desk. Desks are kind of like git repositories.
154+Urbit includes a few default desks: `%base`, `%garden`, `%landscape`, `%webterm`
155+and `%bitcoin`.
156+
157+- `%base` - This desk contains the kernel as well as some core agents and utilities.
158+- `%garden` - This desk contains agents and utilities for managing apps, and the
159+ home screen that displays other app tiles.
160+- `%landscape` - This desk contains everything for the Groups app.
161+- `%webterm` - This desk is for the web dojo app.
162+- `%bitcoin` - This desk is for the bitcoin wallet app and bitcoin provider.
163+
164+You'll typically also have a `%kids` desk, which is just a copy of `%base` from
165+upstream that sponsored ships (moons in the case of a planet, planets in the
166+case of a star) sync their `%base` desk from. Any third-party apps you've
167+installed will also have their own desks.
168+
169+Each desk will typically have a few default directories. The directories are as
170+follows:
171+
172+```
173+desk
174+├── app
175+├── gen
176+├── lib
177+├── mar
178+├── sur
179+├── sys <- on %base desk only
180+├── ted
181+└── tests
182+```
183+
184+- `app`: Gall agents.
185+- `gen`: Generators.
186+- `lib`: Libraries - these would typically be imported with the `/+` Ford rune.
187+- `mar`: `mark` files, which are filetype definitions.
188+- `sur`: Structures - these typically contain type definitions and structures,
189+ and would be imported with the `/-` Ford rune.
190+- `sys`: Kernel files and standard library. Only the `%base` desk has this
191+ directory, it's omitted entirely in all other desks.
192+- `ted`: Threads.
193+- `tests`: Unit tests, to be run by the `%test` thread. This is often omitted.
194+
195+This directory hierarchy is not strictly enforced, but most tools expect things
196+to be in their right place. Any of these folders can be omitted if they'd
197+otherwise be empty.
198+
199+As mentioned, the `%base` desk alone includes a `/sys` directory containing the
200+kernel and standard libraries. It looks like this:
201+
202+```
203+sys
204+├── arvo.hoon
205+├── hoon.hoon
206+├── lull.hoon
207+├── vane
208+│ ├── ames.hoon
209+│ ├── behn.hoon
210+│ ├── clay.hoon
211+│ ├── dill.hoon
212+│ ├── eyre.hoon
213+│ ├── gall.hoon
214+│ ├── iris.hoon
215+│ └── jael.hoon
216+└── zuse.hoon
217+```
218+
219+- `arvo.hoon`: Source code for Arvo itself.
220+- `hoon.hoon`: Hoon standard library.
221+- `lull.hoon`: Mostly structures and type definitions for interacting with
222+ vanes.
223+- `vane`: This directory contains the source code for each of the vanes.
224+- `zuse.hoon`: This is an extra utility library. It mostly contains
225+ cryptographic functions and functions for dealing with web data like JSON.
226+
227+In addition to the directories discussed, there's a handful of special files a
228+desk might contain. All of them live in the root of the desk, and all are
229+optional in the general case, except for `sys.kelvin`.
230+
231+- `sys.kelvin`: Specifies the kernel version with which the desk is compatible.
232+ This is the only mandatory file in a desk.
233+- `desk.bill`: Specifies Gall agents to be auto-started upon desk installation.
234+- `desk.ship`: If the desk is being republished, the original publisher can be
235+ specified here.
236+- `desk.docket-0`: Configures the front-end, tile, and other metadata for desks
237+ which include a home screen app.
238+
239+Each desk must be self-contained; it must include all the `mark`s, libraries,
240+threads, etc, that it needs. The one exception is the kernel and standard
241+libraries from the `%base` desk. Agents, threads and generators in other desks
242+all have these libraries available to them in their subject.
243+
244+## APIs
245+
246+You should now have a general idea of the different parts of Arvo, but how does
247+a Gall agent interact with these things?
248+
249+There are two basic ways of interacting with other parts of the system: By
250+scrying them, and by passing them messages and receiving messages in response.
251+There are also two basic things to interact with: Vanes, and other agents.
252+
253+- Scries: The scry system allows you to access the state of other agents and
254+ vanes in a read-only fashion. Scries can be performed from any context with
255+ the dotket (`.^`) rune. Each vane has "scry endpoints" which define what you
256+ can read, and these are comprehensively documented in the Scry Reference of
257+ each vane's section of the [Arvo documentation](/docs/arvo/overview). Agents
258+ can also define scry endpoints in the `+on-peek` arm of their agent core.
259+ Scries can only be done on the local ship, it is not yet possible to perform
260+ scries over the network. There is a separate [guide to
261+ scries](/docs/arvo/concepts/scry) which you might like to read through for
262+ more details.
263+- Messages:
264+ - Vanes: Each vane has a number of `task`s it can be passed and `gift`s it can
265+ respond with in its respective section of `lull.hoon`. These might do all
266+ manner of things, depending on the vane. For example, Iris might fetch an
267+ external HTTP resource for you, Clay might read or build a specified file,
268+ etc. The tasks and gifts of each vane are comprehensively documented in the
269+ API Reference of each vane's section of the [Arvo
270+ documentation](/docs/arvo/overview).
271+ - Agents: These can be `%poke`d with some data, and can also be `%watch`ed,
272+ which means to subscribe for updates. We'll discuss these in detail later in
273+ the guide.
274+
275+Here's a simplified diagram of the ways an agent can interact with other parts
276+of the system:
277+
278+![api diagram](https://m.tinnus-napbus.xyz/pub/api-diagram.svg)
279+
280+Things like `on-poke` are arms of the agent core. Don't worry about their
281+meaning for now, we'll discuss them in detail later in the guide.
282+
283+Inter-agent messaging can occur over the network, so you can interact with
284+agents on other ships as well as local ones. You can only talk to local vanes,
285+but some vanes like Clay are able to make requests to other ships on your
286+behalf. Note this summary is simplified - vanes don't just talk in tasks and
287+gifts in all cases. For example, requests from HTTP clients through Eyre (the
288+webserver vane) behave more like those from agents than vanes, and a couple of
289+other vanes also have some different behaviours. Agent interactions are also a
290+little more complicated, and we'll discuss that later, but the basic patterns
291+described here cover the majority of cases.
292+
293+## Environment Setup
294+
295+Before proceeding with the Gall Guide, you'll need to have an appropriate text
296+editor installed and configured, and know how to work with a fake ship for
297+development. Best practices are described in the [environment setup
298+guide](/docs/development/environment).
content/docs/userspace/gall-guide/10-scry.mdnew file+352
@@ -0,0 +1,352 @@
1++++
2+title = "10. Scries"
3+weight = 50
4+template = "doc.html"
5++++
6+
7+In this lesson we'll look at scrying agents, as well as how agents handle such
8+scries. If you're not at all familiar with performing scries in general, have a
9+read through the [Scry Guide](/docs/arvo/concepts/scry), as well as the [dotket
10+rune documentation](/docs/hoon/reference/rune/dot#-dotket).
11+
12+## Scrying
13+
14+Scries are purely read-only requests to vanes and agents which can be initiated
15+from anywhere in any code, during its evaluation. If successful, the requested
16+data is returned immediately to that point in the code, otherwise it crashes.
17+This is in contrast to passing around `card`s, which aren't read-only and which
18+can only be produced when evaluation of the arm is complete, and for which any
19+response will come back separately.
20+
21+Technically, Arvo only lets you scry vanes. When you scry a Gall agent, you
22+actually scry Gall itself, which interprets the request, runs it on the
23+specified agent, and then returns the result. Scries are performed with the
24+[dotket](/docs/hoon/reference/rune/dot#-dotket) (`.^`) rune. Here's a summary of
25+their format:
26+
27+![scry summary diagram](https://media.urbit.org/docs/arvo/scry-diagram-v2.svg)
28+
29+A note on `care`s: Cares are most fully exploited by Clay, where they specify
30+submodules and have tightly defined behaviors. For Gall agents, most of these
31+don't have any special behavior, and are just used to indicate the general kind
32+of data produced by the endpoint. There are a handful of exceptions to this:
33+`%d`, `%e`, `%u` and `%x`.
34+
35+#### `%d`
36+
37+A scry to Gall with a `%d` `care` and no `path` will produce the `desk` in which the specified agent resides. For example:
38+
39+```
40+> .^(desk %gd /=hark-store=)
41+%garden
42+> .^(desk %gd /=hood=)
43+%base
44+```
45+
46+#### `%e`
47+
48+A scry to Gall with a `%e` `care`, a `desk` rather than agent in the `desk`
49+field of the above diagram, and no path, will produce a set of all installed
50+agents on that desk and their status. For example:
51+
52+```
53+> .^((set [=dude:gall live=?]) %ge /=garden=)
54+{ [dude=%hark-system-hook live=%.y]
55+ [dude=%treaty live=%.y]
56+ [dude=%docket live=%.y]
57+ [dude=%settings-store live=%.y]
58+ [dude=%hark-store live=%.y]
59+}
60+```
61+
62+#### `%u`
63+
64+A scry to Gall with a `%u` `care` and no `path` will check whether or not the specified agent is installed and running:
65+
66+```
67+> .^(? %gu /=btc-wallet=)
68+%.y
69+> .^(? %gu /=btc-provider=)
70+%.n
71+> .^(? %gu /=foobar=)
72+%.n
73+```
74+
75+#### `%x`
76+
77+A scry to Gall with a `%x` `care` will be passed to the agent for handling. Gall
78+handles `%x` specially, and expects an extra field at the end of the `path` that
79+specifies the `mark` to return. Gall will take the data produced by the
80+specified endpoint and try convert it to the given mark, crashing if the mark
81+conversion fails. The extra field specifying the mark is not passed through to
82+the agent itself. Here's a couple of examples:
83+
84+```
85+> =store -build-file /=landscape=/sur/graph-store/hoon
86+
87+> .^(update:store %gx /=graph-store=/keys/noun)
88+[p=~2021.11.18..10.50.41..c914 q=[%keys resources={[entity=~zod name=%dm-inbox]}]]
89+
90+> (crip (en-json:html .^(json %gx /=graph-store=/keys/json)))
91+'{"graph-update":{"keys":[{"name":"dm-inbox","ship":"zod"}]}}'
92+```
93+
94+The majority of Gall agents simply take `%x` `care`s in their scry endpoints,
95+but in principle it's possible for a Gall agent to define a scry endpoint that
96+takes any one of the `care`s listed in the diagram above. An agent's scry
97+endpoints are defined in its `on-peek` arm, which we'll look at next.
98+
99+## Handling scries
100+
101+When a scry is performed on a Gall agent, Gall will strip out some extraneous
102+parts, and deliver it to the agent's `on-peek` arm as a `path`. The `path` will
103+only have two components from the diagram above: The _care_ and the _path_. For
104+example, a scry of `.^(update:store %gx /=graph-store=/keys/noun)` will come
105+into the `on-peek` arm of `%graph-store` as `/x/keys`.
106+
107+The `on-peek` arm produces a `(unit (unit cage))`. The reason for the double
108+`unit` is that Arvo interprets `~` to mean the scry endpoint doesn't exist at
109+all, and interprets `[~ ~]` to mean the endpoint exists but the requested data
110+does not. In either case the dotket expression which initiated the scry will
111+crash. The `cage` will contain the actual data to return.
112+
113+The `on-peek` arm, therefore, begins like so:
114+
115+```hoon
116+++ on-peek
117+ |= =path
118+ ^- (unit (unit cage))
119+ ....
120+```
121+
122+Typically, you'd handle the `path` similarly to `on-watch`, as we discussed in the lesson on subscriptions. You'd use something like a wutlus expression to test the type of the `path`, defining your scry endpoints like so:
123+
124+```hoon
125+?+ path (on-peek:def path)
126+ [%x %some %path ~] ....
127+ [%x %foo ~] ....
128+ [%x %blah @ ~]
129+ =/ =ship (slav %p i.t.t.path)
130+ .....
131+....
132+```
133+
134+Each endpoint would then compose the `(unit (unit cage))`. The simplest way to
135+format it is like:
136+
137+```hoon
138+``noun+!>('some data')
139+```
140+
141+If it requires a more complex expression to retrieve or compose the data, you
142+can do something like:
143+
144+```hoon
145+:- ~ :- ~ :- %some-mark
146+!> ^- some-type
147+:+ 'foo'
148+ 'bar'
149+'baz'
150+```
151+
152+Previously we discussed custom `mark` files. Such mark files are most commonly
153+used when the data might be accessed through Eyre's HTTP API, and therefore
154+required JSON conversion methods. We'll cover such things in part two of the
155+Gall Guide, but note that if that's the case for your agent, you may wish to
156+also have your scry endpoints return data with your custom `mark` so it can
157+easily be converted to JSON when accessed from the web.
158+
159+In some cases, typically with scry `path`s that contain wildcards like the `[%x %blah @ ~]` example above, your agent may not always be able to find the
160+requested data. In such cases, you can just produce a cell of `[~ ~]` for the
161+`(unit (unit cage))`. Keep in mind, however, that this will result in a crash
162+for the dotket expression which initiated the scry. In some cases you may want
163+that, but in other cases you may not, so instead you could wrap the data inside
164+the `vase` in a `unit` and have _that_ be null instead. It all depends on the
165+needs of your particular application.
166+
167+## Example
168+
169+Here's a simple example agent with three scry endpoints:
170+
171+#### `peeker.hoon`
172+
173+```hoon
174+/+ default-agent, dbug
175+|%
176++$ versioned-state
177+ $% state-0
178+ ==
179++$ state-0 [%0 data=(map @p @t)]
180++$ card card:agent:gall
181+--
182+%- agent:dbug
183+=| state-0
184+=* state -
185+^- agent:gall
186+|_ =bowl:gall
187++* this .
188+ def ~(. (default-agent this %.n) bowl)
189+++ on-init
190+ ^- (quip card _this)
191+ `this
192+++ on-save
193+ ^- vase
194+ !>(state)
195+++ on-load
196+ |= old-state=vase
197+ ^- (quip card _this)
198+ =/ old !<(versioned-state old-state)
199+ ?- -.old
200+ %0 `this(state old)
201+ ==
202+++ on-poke
203+ |= [=mark =vase]
204+ ^- (quip card _this)
205+ ?> =(src.bowl our.bowl)
206+ ?+ mark (on-poke:def mark vase)
207+ %noun
208+ `this(data (~(put by data) !<([@p @t] vase)))
209+ ==
210+++ on-watch on-watch:def
211+++ on-leave on-leave:def
212+++ on-peek
213+ |= =path
214+ ^- (unit (unit cage))
215+ ?+ path (on-peek:def path)
216+ [%x %all ~] ``noun+!>(data)
217+ ::
218+ [%x %has @ ~]
219+ =/ who=@p (slav %p i.t.t.path)
220+ ``noun+!>(`?`(~(has by data) who))
221+ ::
222+ [%x %get @ ~]
223+ =/ who=@p (slav %p i.t.t.path)
224+ =/ maybe-res (~(get by data) who)
225+ ?~ maybe-res
226+ [~ ~]
227+ ``noun+!>(`@t`u.maybe-res)
228+ ==
229+++ on-agent on-agent:def
230+++ on-arvo on-arvo:def
231+++ on-fail on-fail:def
232+--
233+```
234+
235+The agent's `on-poke` arm takes a cell of `[@p @t]` and saves it in the agent's
236+state, which contains a `(map @p @t)` called `data`. The `on-peek` arm is:
237+
238+```hoon
239+++ on-peek
240+ |= =path
241+ ^- (unit (unit cage))
242+ ?+ path (on-peek:def path)
243+ [%x %all ~] ``noun+!>(data)
244+ ::
245+ [%x %has @ ~]
246+ =/ who=@p (slav %p i.t.t.path)
247+ ``noun+!>(`?`(~(has by data) who))
248+ ::
249+ [%x %get @ ~]
250+ =/ who=@p (slav %p i.t.t.path)
251+ =/ maybe-res (~(get by data) who)
252+ ?~ maybe-res
253+ [~ ~]
254+ ``noun+!>(`@t`u.maybe-res)
255+ ==
256+```
257+
258+It defines three scry endpoints, all using a `%x` `care`: `/x/all`,
259+`/x/has/[ship]`, and `/x/get/[ship]`. The first will simply return the entire
260+`(map @p @t)` in the agent's state. The second will check whether the given ship
261+is in the map and produce a `?`. The third will produce the `@t` for the given
262+`@p` if it exists in the map, or else return `[~ ~]` to indicate the data
263+doesn't exist, producing a crash in the dotket expression.
264+
265+Let's try it out. Save the agent above as `/app/peeker.hoon` in the `%base`
266+desk, `|commit %base` and start the agent with `|rein %base [& %peeker]`.
267+
268+First, let's add some data to the map:
269+
270+```
271+> :peeker [~zod 'foo']
272+>=
273+> :peeker [~nut 'bar']
274+>=
275+> :peeker [~wet 'baz']
276+>=
277+```
278+
279+Now if we use `dbug` to inspect the state, we'll see the data has been added:
280+
281+```
282+> {[p=~wet q='baz'] [p=~nut q='bar'] [p=~zod q='foo']}
283+> :peeker +dbug [%state %data]
284+>=
285+```
286+
287+Next, let's try the `/x/all` scry endpoint:
288+
289+```
290+> .^((map @p @t) %gx /=peeker=/all/noun)
291+{[p=~wet q='baz'] [p=~nut q='bar'] [p=~zod q='foo']}
292+```
293+
294+The `/x/has/[ship]` endpoint:
295+
296+```
297+> .^(? %gx /=peeker=/has/~zod/noun)
298+%.y
299+> .^(? %gx /=peeker=/has/~wet/noun)
300+%.y
301+> .^(? %gx /=peeker=/has/~nes/noun)
302+%.n
303+```
304+
305+And finally, the `/x/get/[ship]` endpoint:
306+
307+```
308+> .^(@t %gx /=peeker=/get/~zod/noun)
309+'foo'
310+> .^(@t %gx /=peeker=/get/~wet/noun)
311+'baz'
312+```
313+
314+We'll now try scrying for a ship that doesn't exist in the map. Note that the
315+resulting crash will wipe the dojo's subject, so don't try this if you've got
316+anything pinned there that you want to keep.
317+
318+```
319+~zod:dojo> .^(@t %gx /=peeker=/get/~nes/noun)
320+crash!
321+```
322+
323+## Summary
324+
325+- Scries are read-only requests to vanes or agents which can be done inside any
326+ code, during its evaluation.
327+- Scries are performed with the dotket (`.^`) rune.
328+- Scries will fail if the scry endpoint does not exist, the requested data does
329+ not exist, or the data does not nest in the return type specified.
330+- Scries can only be performed on the local ship, not on remote ships.
331+- Gall scries with an agent name in the `desk` field will be passed to that
332+ agent's `on-peek` arm for handling.
333+- Gall scries with a `%x` `care` take a `mark` at the end of the scry path,
334+ telling gall to convert the data returned by the scry endpoint to the mark
335+ specified.
336+- The `on-peek` arm takes a `path` with the `care` in the head and the path part
337+ of the scry in the tail, like `/x/some/path`.
338+- The `on-peek` arm produces a `(unit (unit cage))`. The outer `unit` is null if
339+ the scry endpoint does not exist, and the inner `unit` is null if the data
340+ does not exist.
341+
342+## Exercises
343+
344+- Have a read through the [Scry Guide](/docs/arvo/concepts/scry).
345+- Have a read through the [dotket rune
346+ documentation](/docs/hoon/reference/rune/dot#-dotket).
347+- Run through the [Example](#example) yourself if you've not done so already.
348+- Try adding another scry endpoint to the `peeker.hoon` agent, which uses a
349+ [`wyt:by`](/docs/hoon/reference/stdlib/2i#wytby) map function to produce the
350+ number of items in the `data` map.
351+- Have a look through the `on-peek` arms of some other agents on your ship, and
352+ try performing some scries to some of the endpoints.
content/docs/userspace/gall-guide/11-fail.mdnew file+138
@@ -0,0 +1,138 @@
1++++
2+title = "11. Failure"
3+weight = 55
4+template = "doc.html"
5++++
6+
7+In this lesson we'll cover the last agent arm we haven't touched on yet:
8+`on-fail`. We'll also touch on one last concept, which is the _helper core_.
9+
10+# Failures
11+
12+When crashes or errors occur in certain cases, Gall passes them to an agent's
13+`on-fail` arm for handling. This arm is very seldom used, almost all agents
14+leave it for `%default-agent` to handle, which just prints the error message to
15+the terminal. While you're unlikely to use this arm, we'll briefly go over its
16+behavior for completeness.
17+
18+`on-fail` takes a `term` error message and a `tang`, typically containing a
19+stack trace, and often with additional messages about the error. If it weren't
20+delegated to `on-fail:def`, it would begin with:
21+
22+```hoon
23+++ on-fail
24+ |= [=term =tang]
25+ ^- (quip card _this)
26+ ....
27+```
28+
29+Gall calls `on-fail` in four cases:
30+
31+- When there's a crash in the `on-arvo` arm.
32+- When there's a crash in the `on-agent` arm.
33+- When there's a crash in the `on-leave` arm.
34+- When an agent produces a `%watch` card but the `wire`, ship, agent and `path`
35+ specified are the same as an existing subscription.
36+
37+For an `on-arvo` failure, the `term` will always be `%arvo-response`, and the
38+`tang` will contain a stack trace.
39+
40+For `on-agent`, the `term` will be the head of the `sign` (`%poke-ack`, `%fact`,
41+etc). The `tang` will contain a stack trace and a message of "closing
42+subscription".
43+
44+For an `on-leave` failure, the `term` will always be `%leave`, and the `tang`
45+will contain a stack trace.
46+
47+For a `%watch` failure, the `term` will be `%watch-not-unique`. The `tang` will
48+include a message of "subscribe wire not unique", as well as the agent name, the
49+`wire`, the target ship and the target agent.
50+
51+How you might handle these cases (if you wanted to manually handle them) depends
52+on the logic of your particular agent.
53+
54+## Helper core
55+
56+Back in the lesson on lustar virtual arms, we briefly mentioned a common pattern
57+is to define an alias of `hc` for a "helper core" like:
58+
59+```hoon
60++* this .
61+ def ~(. (default-agent this %.n) bowl)
62+ hc ~(. +> bowl)
63+```
64+
65+A helper core is a separate core composed into the subject of the agent core,
66+containing useful functions for use by the agent arms. Such a helper core would
67+typically contain functions that would only ever be used internally by the
68+agent - more general functions would typically be included in a separate `/lib`
69+library and imported with a [faslus](/docs/arvo/ford/ford#ford-runes) (`/+`)
70+rune.
71+
72+The conventional pattern is to have the helper core _below_ the agent core, so the structure of the agent file is like:
73+
74+```
75+[imports]
76+[state types core]
77+[agent core]
78+[helper core]
79+```
80+
81+Recall that the build system will implicitly compose any discrete expressions.
82+If we simply added the helper core below the agent core, the agent core would be
83+composed into the subject of the helper core, which is the opposite of what we
84+want. Instead, we must inversely compose the two cores with a
85+[tisgal](/docs/hoon/reference/rune/tis#-tisgal) (`=<`) rune. We add the tisgal
86+rune directly above the agent core like:
87+
88+```hoon
89+.....
90+=<
91+|_ =bowl:gall
92++* this .
93+ def ~(. (default-agent this %|) bowl)
94+ hc ~(. +> bowl)
95+++ on-init
96+.....
97+```
98+
99+We can then add the helper core below the agent core. The helper core is most
100+typically a `door` like the agent core, also with the `bowl` as its sample. This
101+is just so any functions you define in it have ready access to the `bowl`. It
102+would look like:
103+
104+```hoon
105+|_ =bowl:gall
106+++ some-function ...
107+++ another ....
108+++ etc ...
109+--
110+```
111+
112+Back in the lustar virtual arm of the agent core, we give it an alias of `hc` and call it like so:
113+
114+```hoon
115+hc ~(. +> bowl)
116+```
117+
118+The composition will put the helper core in the tail of the tail of the agent
119+core's subject, so we use a [censig](/docs/hoon/reference/rune/cen#-censig)
120+expression to call `+>` of the subject (`.`) with the `bowl` as its sample.
121+After that, any agent arms can make use of helper core functions by calling them
122+like `(some-function:hc ....)`.
123+
124+## Summary
125+
126+- `on-fail` is called in certain cases of crashes or failures.
127+- Crashes in the `on-agent`, `on-arvo`, or `on-watch` arms will trigger a call
128+ to `on-fail`.
129+- A non-unique `%watch` `card` will also trigger a call to `on-fail`.
130+- `on-fail` is seldom used - most agents just leave it to `%default-agent` to
131+ handle, which just prints the error to the terminal.
132+- A helper core is an extra core of useful functions, composed into the subject
133+ of the agent core.
134+- Helper cores are typically placed below the agent core, and composed with a
135+ tisgal (`=<`) rune.
136+- The helper core is typically a `door` with the `bowl` as a sample.
137+- The helper core is typically given an alias of `hc` in the lustar virtual arm
138+ of the agent core.
content/docs/userspace/gall-guide/12-next-steps.mdnew file+42
@@ -0,0 +1,42 @@
1++++
2+title = "12. Next Steps"
3+weight = 55
4+template = "doc.html"
5++++
6+
7+We've now covered all the arms of a Gall agent, and everything you need to know
8+to start writing your own agent.
9+
10+The one thing we haven't touched on is front-end development and integration,
11+Eyre's HTTP API for communicating with agents from the web, and dealing with
12+JSON data. A second part to the Gall Guide is coming soon, and will focus
13+exclusively on these aspects. In the mean time though, you can refer to the
14+following documents for help writing a web front-end for your app:
15+
16+- [Eyre's external API reference](/docs/arvo/eyre/external-api-ref) - This
17+ explains Eyre's HTTP API, through which a browser or other HTTP client can
18+ interact with a Gall agent.
19+- [Eyre's usage guide](/docs/arvo/eyre/guide) - This walks through examples of
20+ using Eyre's HTTP API.
21+- [JSON guide](/docs/hoon/guides/json-guide) - This walks through the basics of
22+ converting Hoon data structures to JSON, for use with a web client. It also
23+ covers JSON conversion methods in `mark` files.
24+- [Zuse reference](/docs/hoon/reference/zuse/table-of-contents) - This contains
25+ documentation of all JSON encoding and decoding functions included in the
26+ `zuse.hoon` utility library.
27+- [The software distribution guide](/docs/userspace/dist/dist) - This covers
28+ everything you need to know to distribute apps to other ships. It includes
29+ details of bundling a web front-end and serving it to the user in the browser.
30+
31+In addition to these documents about creating a web-based user interface for
32+your app, there are some other guides you might like to have a look at:
33+
34+- [Threads guide](/docs/userspace/threads/overview) - Threads are like transient
35+ agents, typically used for handling complex I/O functionality for Gall
36+ agents - like interacting with an external HTTP API.
37+- [The software distribution guide](/docs/usespace/dist/dist) - This explains
38+ how to set up a desk for distribution, so other people can install your app.
39+
40+For more development resources, and for ways to get involved with the Urbit
41+development community, see the [Urbit Developers
42+site](https://developers.urbit.org/).
content/docs/userspace/gall-guide/2-agent.mdnew file+300
@@ -0,0 +1,300 @@
1++++
2+title = "2. The Agent Core"
3+weight = 10
4+template = "doc.html"
5++++
6+
7+A Gall agent is a `door` with exactly ten arms. Each arm is responsible for
8+handling certain kinds of events that Gall feeds in to the agent. A `door` is
9+just a `core` with a sample - it's made with the
10+[barcab](/docs/hoon/reference/rune/bar#_-barcab) rune (`|_`) instead of the
11+usual [barcen](/docs/hoon/reference/rune/bar#-barcen) rune (`|%`).
12+
13+## The ten arms
14+
15+We'll discuss each of the arms in detail later. For now, here's a quick summary.
16+The arms of an agent can be be roughly grouped by purpose:
17+
18+### State management
19+
20+These arms are primarily for initializing and upgrading an agent.
21+
22+- `on-init`: Handles starting an agent for the first time.
23+- `on-save`: Handles exporting an agent's state - typically as part of the
24+ upgrade process but also when suspending, uninstalling and debugging.
25+- `on-load`: Handles loading a previously exported agent state - typically as
26+ part of the upgrade process but also when resuming or reinstalling an agent.
27+
28+### Request handlers
29+
30+These arms handle requests initiated by outside entities, e.g. other agents,
31+HTTP requests from the front-end, etc.
32+
33+- `on-poke`: Handles any calls from outside processes that aren't subscriptions,
34+ i.e. one-time actions.
35+- `on-watch`: Handles subscription requests from other entities.
36+- `on-leave`: Handles unsubscribe requests from other, currently subscribed
37+ entities.
38+
39+### Response handlers
40+
41+These two arms handle responses to requests our agent previously initiated.
42+
43+- `on-agent`: Handles subscription updates and request acknowledgements from
44+ other agents.
45+- `on-arvo`: Handles subscription updates, request acknowledgements, and
46+ responses from vanes.
47+
48+### Scry handler
49+
50+- `on-peek`: Handles local read-only requests.
51+
52+### Failure handler
53+
54+- `on-fail`: Handles certain kinds of crash reports from Gall. Most agents don't
55+ make use of this arm and just leave it with a basic default.
56+
57+## Bowl
58+
59+The sample of the `door` is a `bowl:gall`. Every time an event triggers the
60+agent, Gall populates the bowl with things like the current date-time, entropy,
61+subscription information, which ship the request came from, etc, so that all the
62+arms of the agent have access to that data. For the exact structure and contents
63+of the bowl, have a read through [its entry in the Gall vane types
64+documentation](/docs/arvo/gall/data-types#bowl).
65+
66+## State
67+
68+If you've worked through [Hoon School](/docs/hoon/hoon-school/intro), you may
69+recall that a core is a cell of `[battery payload]`. The battery is the core
70+itself compiled into nock, and the payload is the subject which it operates on.
71+
72+For an agent, the payload will at least contain the bowl, the usual standard
73+library functions, and the **state** of the agent. If your agent were for an
74+address book app, it might keep a `map` of ships to address book entries. It
75+might add entries, delete entries, and modify entries. This address book `map`
76+would be part of the state stored in the payload.
77+
78+## Transition function
79+
80+If you recall from the prologue, the whole Arvo operating system works on the
81+basis of a simple transition function `(event, oldState) -> (effects, newState)`. Gall agents also function the same way. Eight of an agent's ten arms
82+produce the same thing, a cell of:
83+
84+- Head: A list of effects called `card`s (which we'll discuss later).
85+- Tail: A new agent core, possibly with a modified payload.
86+
87+It goes something like this:
88+
89+1. An event is routed to Gall.
90+2. Gall calls the appropriate arm of the agent, depending on the kind of event.
91+3. That arm processes the event, returning a list `card`s to be sent off, and
92+ the agent core itself with a modified state in the payload.
93+4. Gall sends the `card`s off and saves the modified agent core.
94+5. Rinse and repeat.
95+
96+## Virtualization
97+
98+When a crash occurs in the kernel, the system usually aborts the computation and
99+discards the event as though it never happened. Gall on the other hand
100+virtualizes all its agents, so this doesn't happen. Instead, when a crash occurs
101+in an agent, Gall intercepts the crash and takes appropriate action depending on
102+the kind of event that caused it. For example, if a poke from another ship
103+caused a crash in the `on-poke` arm, Gall will respond to the poke with a
104+"nack", a negative acknowledgement, telling the original ship the poke was
105+rejected.
106+
107+What this means is that you can intentionally design your agent to crash in
108+cases it can't handle. For example, if a poke comes in with an unexpected
109+`mark`, it crashes. If a permission check fails, it crashes. This is quite
110+different to many programs written in procedural languages, which must handle
111+all exceptions to avoid crashing.
112+
113+## Example
114+
115+Here's about the simplest valid Gall agent:
116+
117+```hoon
118+|_ =bowl:gall
119+++ on-init `..on-init
120+++ on-save !>(~)
121+++ on-load |=(vase `..on-init)
122+++ on-poke |=(cage !!)
123+++ on-watch |=(path !!)
124+++ on-leave |=(path `..on-init)
125+++ on-peek |=(path ~)
126+++ on-agent |=([wire sign:agent:gall] !!)
127+++ on-arvo |=([wire sign-arvo] !!)
128+++ on-fail |=([term tang] `..on-init)
129+--
130+```
131+
132+This is just a dummy agent that does absolutely nothing - it has no state and
133+rejects all messages by crashing. We'll get to what each of the arms do later.
134+For now, we'll just consider a few particular points.
135+
136+Firstly, note its structure - it's a `door` (created with `|_`) with a sample of
137+`bowl:gall` and the ten arms described earlier.
138+
139+Secondly, you'll notice some of the arms return:
140+
141+```hoon
142+`..on-init
143+```
144+
145+A backtick at the beginning is an irregular syntax meaning "prepend with null",
146+so for example in the dojo:
147+
148+```
149+> `50
150+[~ 50]
151+```
152+
153+The next part has a dot-dot-arm syntax, which means "the parent core of the
154+specified arm". Since we've specified the arm as `on-init`, its parent is our
155+whole agent. In the [transition function](#transition-function) section we
156+mentioned that most arms return a list of effects called `card`s and a new agent
157+core. Since an empty list is `~`, we've created a cell that fits that
158+description.
159+
160+Let's examine our agent. In the dojo of a fake ship, mount the `%base` desk with
161+`|mount %base`. On the Unix side, navigate to `/path/to/fake/ship/base`, and save
162+the above agent in the `/app` directory as `skeleton.hoon`. Back in the dojo,
163+commit the file to the desk with `|commit %base`.
164+
165+For the moment we won't install our `%skeleton` agent. Instead, we'll use the
166+`%build-file` thread to build it and save it in the dojo's subject so we can
167+have a look. Run the following in the dojo:
168+
169+```
170+> =skeleton -build-file %/app/skeleton/hoon
171+```
172+
173+Now, let's have a look:
174+
175+```
176+> skeleton
177+< 10.fxw
178+ [ bowl
179+ [ [our=@p src=@p dap=@tas]
180+ [ wex=nlr([p=[wire=/ ship=@p term=@tas] q=[acked=?(%.y %.n) path=/]])
181+ sup=nlr([p=it(/) q=[p=@p q=/]])
182+ ]
183+ act=@ud
184+ eny=@uvJ
185+ now=@da
186+ byk=[p=@p q=@tas r=?([%da p=@da] [%tas p=@tas] [%ud p=@ud])]
187+ ]
188+ <17.zbp 33.wxp 14.dyd 53.vlb 77.wir 232.wfe 51.qbt 123.zao 46.hgz 1.pnw %140>
189+ ]
190+>
191+```
192+
193+The dojo pretty-prints cores with a format of `number-of-arms.hash`. You can see
194+the head of `skeleton` is `10.fxw` - that's the battery of the core, our 10-arm
195+agent. If we try printing the head of `skeleton` we'll see it's a whole lot of
196+compiled `nock`:
197+
198+```
199+> -.skeleton
200+[ [ 11
201+ [ 1.953.460.339
202+ 1
203+ [ 7.368.801
204+ 7.957.707.045.546.060.659
205+ 1.852.796.776
206+ 0
207+ ]
208+ [7 15]
209+ 7
210+ 34
211+ ]
212+...(truncated for brevity)...
213+```
214+
215+The battery's not too important, it's not something we'd ever touch in practice.
216+Instead, let's have a look at the core's payload by printing the tail of
217+`skeleton`. We'll see its head is the `bowl:gall` sample we specified, and then
218+the tail is just all the usual standard library functions:
219+
220+```
221+> +.skeleton
222+[ bowl
223+ [ [our=~zod src=~zod dap=%$]
224+ [wex={} sup={}]
225+ act=0
226+ eny=0v0
227+ now=~2000.1.1
228+ byk=[p=~zod q=%$ r=[%ud p=0]]
229+ ]
230+ <17.zbp 33.wxp 14.dyd 53.vlb 77.wir 232.wfe 51.qbt 123.zao 46.hgz 1.pnw %140>
231+]
232+```
233+
234+Currently `skeleton` has no state, but of course in practice you'd want to store
235+some actual data. We'll add `foo=42` as our state with the `=+` rune at the
236+beginning of our agent:
237+
238+```hoon
239+=+ foo=42
240+|_ =bowl:gall
241+++ on-init `..on-init
242+++ on-save !>(~)
243+++ on-load |=(vase `..on-init)
244+++ on-poke |=(cage !!)
245+++ on-watch |=(path !!)
246+++ on-leave |=(path `..on-init)
247+++ on-peek |=(path ~)
248+++ on-agent |=([wire sign:agent:gall] !!)
249+++ on-arvo |=([wire sign-arvo] !!)
250+++ on-fail |=([term tang] `..on-init)
251+--
252+```
253+
254+Save the modified `skeleton.hoon` in `/app` on the `%base` desk like before, and run `|commit %base` again in the dojo. Then, rebuild it with the same `%build-file` command as before:
255+
256+```
257+> =skeleton -build-file %/app/skeleton/hoon
258+```
259+
260+If we again examine our agent core's payload by looking at the tail of
261+`skeleton`, we'll see `foo=42` is now included:
262+
263+```
264+> +.skeleton
265+[ bowl
266+ [ [our=~zod src=~zod dap=%$]
267+ [wex={} sup={}]
268+ act=0
269+ eny=0v0
270+ now=~2000.1.1
271+ byk=[p=~zod q=%$ r=[%ud p=0]]
272+ ]
273+ foo=42
274+ <17.zbp 33.wxp 14.dyd 53.vlb 77.wir 232.wfe 51.qbt 123.zao 46.hgz 1.pnw %140>
275+]
276+```
277+
278+## Summary
279+
280+The key takeways are:
281+
282+- A Gall agent is a `door` with ten arms and a sample of `bowl:gall`.
283+- Each of the ten arms handle different kinds of events - Gall calls the
284+ appropriate arm for the kind event it receives.
285+- The ten arms fit roughly into five categories:
286+ - State management.
287+ - Request handlers.
288+ - Response handlers.
289+ - Scry handler.
290+ - Failure handler.
291+- The state of an agent—the data it's storing—lives in the core's payload.
292+- Most arms produce a list of effects called `card`s, and a new agent core with
293+ a modified state in its payload.
294+
295+## Exercises
296+
297+- Run through the [Example](#example) yourself on a fake ship if you've not done
298+ so already.
299+- Have a look at the [`bowl` entry in the Gall data types
300+ documentation](/docs/arvo/gall/data-types#bowl) if you've not done so already.
content/docs/userspace/gall-guide/3-imports-and-aliases.mdnew file+293
@@ -0,0 +1,293 @@
1++++
2+title = "3. Imports and Aliases"
3+weight = 15
4+template = "doc.html"
5++++
6+
7+In the last lesson we looked at the most basic aspects of a Gall agent's
8+structure. Before we get into the different agent arms in detail, there's some
9+boilerplate to cover that makes life easier when writing Gall agents.
10+
11+## Useful libraries
12+
13+There are a couple of libraries that you'll very likely use in every agent you
14+write. These are [`default-agent`](#default-agent) and [`dbug`](#dbug). In
15+brief, `default-agent` provides simple default behaviours for each agent arm,
16+and `dbug` lets you inspect the state and bowl of an agent from the dojo, for
17+debugging purposes. Every example agent we look at from here on out will make
18+use of both libraries.
19+
20+Let's look at each in more detail:
21+
22+### `default-agent`
23+
24+The `%default-agent` library contains a basic agent with sane default behaviours
25+for each arm. In some cases it just crashes and prints an error message to the
26+terminal, and in others it succeeds but does nothing. It has two primary uses:
27+
28+- For any agent arms you don't need, you can just have them call the matching
29+ function in `%default-agent`, rather than having to manually handle events on
30+ those arms.
31+- A common pattern in an agent is to switch on the input of an arm with
32+ [wutlus](/docs/hoon/reference/rune/wut#-wutlus) (`?+`) runes or maybe
33+ [wutcol](/docs/hoon/reference/rune/wut#wutcol) (`?:`) runes. For any
34+ unexpected input, you can just pass it to the relevant arm of `%default-agent`
35+ rather than handling it manually.
36+
37+The `%default-agent` library lives in `/lib/default-agent/hoon` of the `%base`
38+desk, and you would typically include a copy in any new desk you created. It's
39+imported at the beginning of an agent with the
40+[faslus](/docs/arvo/ford/ford#ford-runes) (`/+`) rune.
41+
42+The library is a wet gate which takes two arguments: `agent` and `help`. The
43+first is your agent core itself, and the second is a `?`. If `help` is `%.y`, it
44+will crash in all cases. If `help` is `%.n`, it will use its defaults. You would
45+almost always have `help` as `%.n`.
46+
47+The wet gate returns a `agent:gall` `door` with a sample of `bowl:gall` - a
48+typical agent core. Usually you would define an alias for it in a virtual arm
49+([explained below](#virtual-arms)) so it's simple to call.
50+
51+### `dbug`
52+
53+The `%dbug` library lets you inspect the state and `bowl` of your agent from the
54+dojo. It includes an `agent:dbug` function which wraps your whole `agent:gall`
55+`door`, adding its extra debugging functionality while transparently passing
56+events to your agent for handling like usual.
57+
58+To use it, you just import `dbug` with a
59+[faslus](/docs/arvo/ford/ford#ford-runes) (`/+`) rune at the beginning, then add
60+the following line directly before the door of your agent:
61+
62+```hoon
63+%- agent:dbug
64+```
65+
66+With that done, you can poke your agent with the `+dbug` generator from the dojo
67+and it will pretty-print its state, like:
68+
69+```
70+> :your-agent +dbug
71+```
72+
73+The generator also has a few useful optional arguments:
74+
75+- `%bowl`: Print the agent's bowl.
76+- `[%state %some-face]`: Print the part of your agent's state that has a face of
77+ `some-face`.
78+- `[%incoming ...]`: Print details of the matching incoming subscription, one
79+ of:
80+ - `[%incoming %ship ~some-ship]`
81+ - `[%incoming %path /part/of/path]`
82+ - `[%incoming %wire /part/of/wire]`
83+- `[%outgoing ...]`: Print details of the matching outgoing subscription, one
84+ of:
85+ - `[%outgoing %ship ~some-ship]`
86+ - `[%outgoing %path /part/of/path]`
87+ - `[%outgoing %wire /part/of/wire]`
88+ - `[outgoing %term %agent-name]`
89+
90+By default it will retrieve your agent's state by using its `on-save` arm, but
91+if you include a scry endpoint with a path of `/x/dbug/state`, it will use that
92+instead.
93+
94+We haven't yet covered some of the concepts described here, so don't worry if
95+you don't fully understand `%dbug`'s functionality - you can refer back here
96+later.
97+
98+## Virtual arms
99+
100+An agent core must have exactly ten arms. However, there's a special kind of
101+"virtual arm" that can be added without actually increasing the core's arm
102+count. A virtual arm is created with the
103+[lustar](/docs/hoon/reference/rune/lus#-lustar) (`+*`) rune, and its purpose is
104+to define _aliases_. It takes a list of pairs of names (aliases) and hoon
105+expressions. When compiled, the aliases defined in the virtual arm are
106+implicitly inserted at the beginning of every other arm of the core, so they all
107+have access to them.
108+
109+A virtual arm in an agent might look something like this:
110+
111+```hoon
112++* this .
113+ def ~(. (default-agent this %.n) bowl)
114+ hc ~(. +> bowl)
115+```
116+
117+`this`, `def` and `hc` are the aliases, and next to each one is the hoon
118+expresion it's aliasing. Notice that unlike most things that take _n_ arguments,
119+a virtual arm is not terminated with a `==`. You can define as many
120+aliases as you like. The three in this example are conventional ones you'd
121+likely use in most agents you write. Their purposes are:
122+
123+```hoon
124+this .
125+```
126+
127+Rather than having to return `..on-init` like we did in the last lesson,
128+instead our arms can just refer to `this` whenever modifying or returning the
129+agent core.
130+
131+```hoon
132+def ~(. (default-agent this %.n) bowl)
133+```
134+
135+This sets up the `%default-agent` library we [described
136+above](#default-agent), so you can easily call its arms like `on-poke:def`,
137+`on-agent:def`, etc.
138+
139+```hoon
140+hc ~(. +> bowl)
141+```
142+
143+This makes it easier to call a function in a _helper core_. We'll introduce
144+helper cores later, so don't worry about this for now.
145+
146+## Additional cores
147+
148+While Gall expects a single 10-arm agent core, it's still possible to include
149+additional cores by composing them into the subject of the agent core itself.
150+The contents of these cores will then be available to arms of the agent core.
151+
152+Usually to compose cores in this way, you'd have to do something like insert
153+[tisgar](/docs/hoon/reference/rune/tis#-tisgar) (`=>`) runes in between them.
154+However, Clay's build system implicitly composes everything in a file by
155+wrapping it in a [tissig](/docs/hoon/reference/rune/tis#-tissig) (`=~`)
156+expression, which means you can just butt separate cores up against one another
157+and they'll all still get composed.
158+
159+You can add as many extra cores as you'd like before the agent core, but
160+typically you'd just add one containing structure definitions for the agent's
161+state, as well as any other useful structures. We'll look at the state in more
162+detail in the next lesson.
163+
164+## Example
165+
166+Here's the `skeleton.hoon` dummy agent from the previous lesson, modified with
167+the concepts discussed here:
168+
169+```hoon
170+/+ default-agent, dbug
171+|%
172++$ card card:agent:gall
173+--
174+%- agent:dbug
175+^- agent:gall
176+|_ =bowl:gall
177++* this .
178+ def ~(. (default-agent this %.n) bowl)
179+++ on-init
180+ ^- (quip card _this)
181+ `this
182+++ on-save on-save:def
183+++ on-load on-load:def
184+++ on-poke on-poke:def
185+++ on-watch on-watch:def
186+++ on-leave on-leave:def
187+++ on-peek on-peek:def
188+++ on-agent on-agent:def
189+++ on-arvo on-arvo:def
190+++ on-fail on-fail:def
191+--
192+```
193+
194+The first line uses the faslus (`/+`) Ford rune to import
195+`/lib/default-agent.hoon` and `/lib/dbug.hoon`, building them and loading them
196+into the subject of our agent so they're available for use. You can read more
197+about Ford runes in the [Ford section of the vane
198+documenation](/docs/arvo/ford/ford#ford-runes).
199+
200+Next, we've added an extra core. Notive how it's not explicitly composed, since
201+the build system will do that for use. In this case we've just added a single
202+`card` arm, which just makes it simpler to reference the `card:agent:gall` type.
203+
204+After that core, we call `agent:dbug` with our whole agent core as its argument.
205+This allows us to use the `dbug` features described earlier.
206+
207+Inside our agent `door`, we've added an extra virtual arm and defined a couple
208+of aliases:
209+
210+```hoon
211++* this .
212+ def ~(. (default-agent this %.n) bowl)
213+```
214+
215+In most of the arms, you see we've been able to replace the dummy code with
216+simple calls to the corresponding arms of `%default-agent`, which we set up and
217+aliased as `def` in the virtual arm. We've also replaced the old `..on-init`
218+with our alias `this` in the `on-init` arm as an example - it makes things a bit
219+simpler.
220+
221+You can save the code above in `/app/skeleton.hoon` of your `%base` desk like
222+before and `|commit %base` in the dojo. Additionally, you can start the agent so
223+we can try out `dbug`. To start it, run the following in the dojo:
224+
225+```
226+> |rein %base [& %skeleton]
227+```
228+
229+For details of using the `|rein` generator, see the [Dojo
230+Tools](/docs/userspace/dist/tools#rein) section of the software distribution
231+documentation.
232+
233+Now our agent should be running, so let's try out `dbug`. In the dojo, let's try
234+poking our agent with the `+dbug` generator:
235+
236+```
237+> ~
238+> :skeleton +dbug
239+>=
240+```
241+
242+It just printed out `~` in green. Our dummy `skeleton` agent doesn't have any
243+state defined, so it's printing out null as a result. Let's try printing the
244+`bowl` instead:
245+
246+```
247+> [ [our=~zod src=~zod dap=%skeleton]
248+ [wex={} sup={}]
249+ act=5
250+ eny
251+ 0v209.tg795.bc2e8.uja0d.11eq9.qp3b3.mlttd.gmf09.q7ro3.6unfh.16jiu.m9lh9.6jlt8.4f847.f0qfh.up08t.3h4l2.qm39h.r3qdd.k1r11.bja8l
252+ now=~2021.11.5..13.28.24..e20e
253+ byk=[p=~zod q=%base r=[%da p=~2021.11.5..12.02.22..f99b]]
254+]
255+> :skeleton +dbug %bowl
256+>=
257+```
258+
259+We'll use `dbug` more throughout the guide, but hopefully you should now have an
260+idea of its basic usage.
261+
262+## Summary
263+
264+The key takeaways are:
265+
266+- Libraries can be imported with `/+`.
267+- `%default-agent` is a library that provides default behaviours for Gall agent
268+ arms.
269+- `%dbug` is a library that lets you inspect the state and `bowl` of an agent
270+ from the dojo, with the `+dbug` generator.
271+- Convenient aliases for hoon expressions can be defined in a virtual arm with
272+ the [lustar](/docs/hoon/reference/rune/lus#-lustar) (`+*`) rune.
273+- `this` is a conventional alias for the agent core itself.
274+- `def` is a conventional alias for accessing arms in the `%default-agent`
275+ library.
276+- Extra cores can be composed into the subject of the agent core. The
277+ composition is done implicitly by the build system. Typically we'd include one
278+ extra core that defines types for our agent's state and maybe other useful
279+ types as well.
280+
281+## Exercises
282+
283+- Run through the [Example](#example) yourself on a fake ship if you've not done
284+ so already.
285+- Have a read through the [Ford rune
286+ documentation](/docs/arvo/ford/ford#ford-runes) for details about importing
287+ libraries, structures and other things.
288+- Try the `+dbug` generator out on some other agents, like `:settings-store +dbug`, `:btc-wallet +dbug`, etc, and try some of its options [described
289+ above](#dbug).
290+- Have a quick look over the source of the `%default-agent` library, locate at
291+ `/lib/default-agent.hoon` in the `%base` desk. We've not yet covered what the
292+ different arms do but it's still useful to get a general idea, and you'll
293+ likely want to refer back to it later.
content/docs/userspace/gall-guide/4-lifecycle.mdnew file+473
@@ -0,0 +1,473 @@
1++++
2+title = "4. Lifecycle"
3+weight = 20
4+template = "doc.html"
5++++
6+
7+In the last lesson we look at some useful bits and pieces that are used as
8+boilerplate in most agents. Now we're going to get into the guts of how agents
9+work, and start looking at what the agent arms do. The first thing we'll look at
10+is the agent's state, and the three arms for managing it: `on-init`, `on-save`,
11+and `on-load`. These arms handle what we call an agent's "lifecycle".
12+
13+## Lifecycle
14+
15+An agent's lifecycle starts when it's first installed. At this point, the
16+agent's `on-init` arm is called. This is the _only_ time its `on-init` arm is
17+ever called - its purpose is just to initialize the agent. The `on-init` arm
18+might be very simple and just set an initial value for the state, or even do
19+nothing at all and return the agent core exactly as-is. It may also be more
20+complicated, and perform some [scries](/docs/arvo/concepts/scry) to obtain extra
21+data or check that another agent is also installed. It might send off some
22+`card`s to other agents or vanes to do things like load data in to the
23+`%settings-store` agent, bind an Eyre endpoint, or anything else. It all depends
24+on the needs of a particular agent. If `on-init` fails for whatever reason, the
25+agent installation will fail and be aborted.
26+
27+Once initialized, an agent will just go on doing its thing - processing events,
28+updating its state, producing effects, etc. At some point, you'll likely want to
29+push an update for your agent. Maybe it's a bug fix, maybe you want to add extra
30+features. Whatever the reason, you need to change the source code of your agent,
31+so you commit a modified version of the file to Clay. When this happens, three things happen:
32+
33+- The agent's `on-save` arm is called, which packs the agent's state in a `vase`
34+ and exports it.
35+- The new version of the agent is built and loaded into Gall.
36+- The previously exported `vase` containing the old state is passed to the
37+ `on-load` arm of the newly built agent. The `on-load` arm will process it,
38+ convert it to the new version of the state if necessary, and load it back
39+ into the state of the agent.
40+
41+A `vase` is just a cell of `[type-of-the-noun the-noun]` - it's used extensively
42+for sending data between agents, vanes and ships. A vase is made with the
43+[zapgar](/docs/hoon/reference/rune/zap#-zapgar) (`!>`) rune like
44+`!>(some-data)`, and unpacked with the
45+[zapgal](/docs/hoon/reference/rune/zap#-zapgal) (`!<`) rune like
46+`!<(type-to-extract vase)`. Have a read through the [`vase` section of the type
47+reference for details](/docs/userspace/gall-guide/types#vase).
48+
49+We'll look at the three arms described here in a little more detail, but first
50+we need to touch on the state itself.
51+
52+## Versioned state type
53+
54+In the previous lesson we introduced the idea of composing additional cores into
55+the subject of the agent core. Here we'll look at using such a core to define
56+the type of the agent's state. In principle, we could make it as simple as this:
57+
58+```hoon
59+|%
60++$ my-state-type @ud
61+--
62+```
63+
64+However, when you update your agent as described in the [Lifecycle](#lifecycle)
65+section, you may want to change the type of the state itself. This means
66+`on-load` might find different data types in the vase it receives, depending on
67+the situation. Over time, as you make further changes to the type of the state,
68+this becomes quite complicated.
69+
70+For example, if you were creating an agent for a To-Do task management app, your
71+tasks might initially have a simple `?` to specify whether they're complete or
72+not. Something like:
73+
74+```hoon
75+(map task=@t done=?)
76+```
77+
78+At some point, you might want to add a third status to represent "in progress",
79+which might involve changing `done` to a tagged union like:
80+
81+```hoon
82+(map title=@t status=?(%todo %done %work))
83+```
84+
85+The conventional way to keep this managable is to have _versioned states_. The
86+first version of the state would typically be called `state-0`, and its head
87+would be tagged with `%0`. Then, when you change the state's type in an update,
88+you'd add a new structure called `state-1` and tag its head with `%1`. The next
89+would then be `state-2`, and so on. In addition to each of those individual
90+state versions, you'd also define a structure called `versioned-state`, which
91+just contains a union of all the possible states. This way, the vase `on-load`
92+receives can be unpacked to a `versioned-state` type, and then a
93+[wuthep](/docs/hoon/reference/rune/wut#--wuthep) (`?-`) expression can switch on
94+the head (`%0`, `%1`, `%2`, etc) and process each one appropriately.
95+
96+For example, your state definition core might initially look like:
97+
98+```hoon
99+|%
100++$ versioned-state
101+ $% state-0
102+ ==
103++$ state-0 [%0 tasks=(map title=@t done=?)]
104+--
105+```
106+
107+When you later update your agent with a new state version, you'd change it to:
108+
109+```hoon
110+|%
111++$ versioned-state
112+ $% state-0
113+ state-1
114+ ==
115++$ state-0 [%0 tasks=(map title=@t done=?)]
116++$ state-1 [%1 tasks=(map title=@t status=?(%todo %done %work))]
117+--
118+```
119+
120+## Adding the state
121+
122+Along with a core defining the type of the state, we also need to actually add
123+it to the subject of the core. The conventional way to do this is by adding the following immediately before the agent core itself:
124+
125+```hoon
126+=| state-0
127+=* state -
128+```
129+
130+The first line bunts (produces the default value) of the state type we defined
131+in the previous core, and adds it to the head of the subject _without a face_.
132+The next line uses [tistar](/docs/hoon/reference/rune/tis#-tistar) to give it
133+the name of `state`. You might wonder why we don't just give it a face when we
134+bunt it and skip the tistar part. If we did that, we'd have to refer to `tasks`
135+as `tasks.state`. With tistar, we can just reference `tasks` while also being
136+able to reference the whole `state` when necessary.
137+
138+Note that adding the state like this only happens when the agent is built - from
139+then on the arms of our agent will just modify it.
140+
141+## State management arms
142+
143+We've described the basic lifecycle process and the purpose of each state
144+management arm. Now let's give an overview of each arm separately.
145+
146+### `on-init`
147+
148+This arm takes no argument, and produces a `(quip card _this)`. It's called exactly once, when the agent is first installed, and its purpose is to initialize the agent.
149+
150+`(quip a b)` is equivalent to `[(list a) b]`, see the [types
151+reference](/docs/userspace/gall-guide/types#quip) for details.
152+
153+A `card` is a message to another agent or vane. We'll discuss `card`s in detail
154+later.
155+
156+`this` is our agent core, which we give the `this` alias in the virtual arm
157+described in the previous lesson. The underscore at the beginning is the
158+irregular syntax for the [buccab](/docs/hoon/reference/rune/buc#_-buccab) (`$_`)
159+rune. Buccab is like an inverted bunt - instead of producing the default value
160+of a type, instead it produces the type of some value. So `_this` means "the
161+type of `this`" - the type of our agent core.
162+
163+Recall that in the last lesson, we said that most arms return a cell of
164+`[effects new-agent-core]`. That's exactly what `(quip card _this)` is.
165+
166+### `on-save`
167+
168+This arm takes no argument, and produces a `vase`. Its purpose is to export the
169+state of an agent - the state is packed into the vase it produces. The main time
170+it's called is when an agent is upgraded. When that happens, the agent's state
171+is exported with `on-save`, the new version of the agent is compiled and loaded,
172+and then the state is imported back into the new version of the agent via the
173+[`on-load`](#on-load) arm.
174+
175+As well as the agent upgrade process, `on-save` is also used when an agent is
176+suspended or an app is uninstalled, so that the state can be restored when it's
177+resumed or reinstalled.
178+
179+The state is packed in a vase with the
180+[zapgar](/docs/hoon/reference/rune/zap#-zapgar) (`!>`) rune like `!>(state)`.
181+
182+### `on-load`
183+
184+This arm takes a `vase` and produces a `(quip card _this)`. Its purpose is to
185+import an agent state previously exported with [`on-save`](#on-save). Typically
186+you'd have used a [versioned state](#versioned-state-type) as described above,
187+so this arm would test which state version the imported data has, convert data
188+from an old version to the new version if necessary, and load it into the
189+`state` wing of the subject.
190+
191+The vase would be unpacked with a
192+[zapgal](/docs/hoon/reference/rune/zap#-zapgal) (`!<`) rune, and then typically
193+you'd test its version with a [wuthep](/docs/hoon/reference/rune/wut#--wuthep)
194+(`?-`) expression.
195+
196+## Example
197+
198+Here's a new agent to demonstrate the concepts we've discussed here:
199+
200+```hoon
201+/+ default-agent, dbug
202+|%
203++$ versioned-state
204+ $% state-0
205+ ==
206++$ state-0 [%0 val=@ud]
207++$ card card:agent:gall
208+--
209+%- agent:dbug
210+=| state-0
211+=* state -
212+^- agent:gall
213+|_ =bowl:gall
214++* this .
215+ def ~(. (default-agent this %.n) bowl)
216+++ on-init
217+ ^- (quip card _this)
218+ `this(val 42)
219+++ on-save
220+ ^- vase
221+ !>(state)
222+++ on-load
223+ |= old-state=vase
224+ ^- (quip card _this)
225+ =/ old !<(versioned-state old-state)
226+ ?- -.old
227+ %0 `this(state old)
228+ ==
229+++ on-poke on-poke:def
230+++ on-watch on-watch:def
231+++ on-leave on-leave:def
232+++ on-peek on-peek:def
233+++ on-agent on-agent:def
234+++ on-arvo on-arvo:def
235+++ on-fail on-fail:def
236+--
237+```
238+
239+Let's break it down and have a look at the new parts we've added. First, the
240+state core:
241+
242+```hoon
243+|%
244++$ versioned-state
245+ $% state-0
246+ ==
247++$ state-0 [%0 val=@ud]
248++$ card card:agent:gall
249+--
250+```
251+
252+In `state-0` we've defined the structure of our state, which is just a `@ud`.
253+We've tagged the head with a `%0` constant representing the version number, so
254+`on-load` can easily test the version of data. In `versioned-state` we've
255+created a union and just added our `state-0` type. We've added an extra `card`
256+arm as well, just so we can use `card` as a type, rather than the unweildy
257+`card:agent:gall`.
258+
259+After that core, we have the usual `agent:dbug` call, and then we have this:
260+
261+```hoon
262+=| state-0
263+=* state -
264+```
265+
266+We've just bunted the `state-0` type, which will produce `[%0 val=0]`, pinning
267+it to the head of the subject. Then, we've use
268+[tistar](/docs/hoon/reference/rune/tis#-tistar) (`=*`) to give it a name of
269+`state`.
270+
271+Inside our agent core, we have `on-init`:
272+
273+```hoon
274+++ on-init
275+ ^- (quip card _this)
276+ `this(val 42)
277+```
278+
279+The `a(b c)` syntax is the irregular form of the
280+[centis](/docs/hoon/reference/rune/cen#-centis) (`%=`) rune. You'll likely be
281+familiar with this from recursive functions, where you'll typically call the buc
282+arm of a trap like `$(a b, c d, ...)`. It's the same concept here - we're saying
283+`this` (our agent core) with `val` replaced by `42`. Since `on-init` is only
284+called when the agent is first installed, we're just initializing the state.
285+
286+Next we have `on-save`:
287+
288+```hoon
289+++ on-save
290+ ^- vase
291+ !>(state)
292+```
293+
294+This exports our agent's state, and is called during upgrades, suspensions, etc.
295+We're having it pack the `state` value in a `vase`.
296+
297+Finally, we have `on-load`:
298+
299+```hoon
300+++ on-load
301+ |= old-state=vase
302+ ^- (quip card _this)
303+ =/ old !<(versioned-state old-state)
304+ ?- -.old
305+ %0 `this(state old)
306+ ==
307+```
308+
309+It takes in the old state in a `vase`, then unpacks it to the `versioned-state`
310+type we defined earlier in our state definition core. We then test its head for
311+the version, and load it back into the state of our agent if it matches. This
312+test is a bit redundant at this stage since we only have one state version, but
313+you'll soon see the purpose of it.
314+
315+You can save it as `app/lifecycle.hoon` in the `%base` desk and `|commit %base`.
316+Then, run `|rein %base [& %lifecycle]` to start it.
317+
318+Let's try inspecting our state with `dbug`:
319+
320+```
321+> [%0 val=42]
322+> :state-test +dbug
323+>=
324+```
325+
326+`dbug` can also dig into the state with the `%state` argument, printing the value of the specified face:
327+
328+```
329+> 42
330+> :state-test +dbug [%state %val]
331+>=
332+```
333+
334+Next, we're going to modify our agent and change the structure of the state so we can test out the upgrade process. Here's a modified version, which you can save in `app/lifecycle.hoon` and `|commit %base`:
335+
336+```hoon
337+/+ default-agent, dbug
338+|%
339++$ versioned-state
340+ $% state-0
341+ state-1
342+ ==
343++$ state-0 [%0 val=@ud]
344++$ state-1 [%1 val=[@ud @ud]]
345++$ card card:agent:gall
346+--
347+%- agent:dbug
348+=| state-1
349+=* state -
350+^- agent:gall
351+|_ =bowl:gall
352++* this .
353+ def ~(. (default-agent this %.n) bowl)
354+++ on-init
355+ ^- (quip card _this)
356+ `this(val [27 32])
357+++ on-save
358+ ^- vase
359+ !>(state)
360+++ on-load
361+ |= old-state=vase
362+ ^- (quip card _this)
363+ =/ old !<(versioned-state old-state)
364+ ?- -.old
365+ %1 `this(state old)
366+ %0 `this(state 1+[val.old val.old])
367+ ==
368+++ on-poke on-poke:def
369+++ on-watch on-watch:def
370+++ on-leave on-leave:def
371+++ on-peek on-peek:def
372+++ on-agent on-agent:def
373+++ on-arvo on-arvo:def
374+++ on-fail on-fail:def
375+--
376+```
377+
378+As soon as you `|commit` it, Gall will immediately export the existing state
379+with `on-save`, build the new version of the agent, then import the state back
380+in with `on-load`.
381+
382+In the state definition core, you'll see we've added a new state version with a different structure:
383+
384+```hoon
385++$ versioned-state
386+ $% state-0
387+ state-1
388+ ==
389++$ state-0 [%0 val=@ud]
390++$ state-1 [%1 val=[@ud @ud]]
391++$ card card:agent:gall
392+--
393+```
394+
395+We've also changed the part that adds the state, so it uses the new version instead:
396+
397+```hoon
398+=| state-1
399+=* state -
400+```
401+
402+In `on-init`, we've updated it to initialize the state with a value that fits the new type we've defined:
403+
404+```hoon
405+++ on-init
406+ ^- (quip card _this)
407+ `this(val [27 32])
408+```
409+
410+`on-init` won't be called in this case, but if someone were to directly install
411+this new version of the agent, it would be, so we still need to update it.
412+
413+`on-save` has been left unchanged, but `on-load` has been updated like so:
414+
415+```hoon
416+++ on-load
417+ |= old-state=vase
418+ ^- (quip card _this)
419+ =/ old !<(versioned-state old-state)
420+ ?- -.old
421+ %1 `this(state old)
422+ %0 `this(state 1+[val.old val.old])
423+ ==
424+```
425+
426+We've updated the wuthep expression with a new case that handles our new state
427+type, and for the old state type we've added a function that converts it to the
428+new type - in this case by just duplicating `val` and changing the head-tag from
429+`%0` to `%1`. This is an extremely simple state type transition function, but it
430+would likely be more complicated for an agent with real functionality.
431+
432+Let's now use `dbug` to check out state has successfully been updated to the new
433+type:
434+
435+```
436+> [%1 val=[42 42]]
437+> :lifecycle +dbug
438+>=
439+```
440+
441+## Summary
442+
443+The key takeways are:
444+
445+- The app lifecycle rougly consists of initialization, state export, upgrade,
446+ state import and state version transition.
447+- This is managed by three arms: `on-init`, `on-save` and `on-load`.
448+- `on-init` initializes the agent and is called when it's first installed.
449+- `on-save` exports the agent's state and is usually called during upgrade or
450+ when an app is suspended.
451+- `on-load` imports an agent's state and is usually called during upgrade or
452+ when an app is unsuspended. It typically also handles converting data from old
453+ state versions to new state versions.
454+- The type of an agent's state is typically defined in a separate core.
455+- The state type is typically versioned, with a new type definition for each
456+ version of the state.
457+- The state is initially added by bunting the state type and then naming it
458+ `state` with the tistar (`=*`) rune, so its contents can be referenced
459+ directly.
460+- A `vase` is a cell of `[type-of-the-noun the-noun]`.
461+- `(quip a b)` is the same as `[(list a) b]`, and is the `[effects new-agent-core]` pair returned by many arms of an agent core.
462+
463+## Exercises
464+
465+- Run through the [Example](#example) yourself on a fake ship if you've not done
466+ so already.
467+- Have a look at the [`vase` entry in the type
468+ reference](/docs/userspace/gall-guide/types#vase).
469+- Have a look at the [`quip` entry in the type
470+ reference](/docs/userspace/gall-guide/types#quip).
471+- Try modifying the second version of the agent in the [Example](#example)
472+ section, adding a third state version. Include functions in the wuthep
473+ expression in `on-load` to convert old versions to your new state type.
content/docs/userspace/gall-guide/5-cards.mdnew file+259
@@ -0,0 +1,259 @@
1++++
2+title = "5. Cards"
3+weight = 25
4+template = "doc.html"
5++++
6+
7+As we previously discussed, most arms of an agent core produce a cell of
8+`[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`s in
9+detail. That's what we'll do here. In explaining `card`s we'll touch on some
10+concepts relating to the mechanics of pokes, subscriptions and other things
11+we've not yet covered. Don't worry if you don't understand how it all fits
12+together yet, we just want to give you a basic idea of `card`s so we can then
13+dig into how they work in practice.
14+
15+## `card` type
16+
17+The `card:agent:gall` type (henceforth just `card`) has a slightly complex
18+structure, so we'll walk through it step-by-step.
19+
20+`lull.hoon` defines a `card` like so:
21+
22+```hoon
23++$ card (wind note gift)
24+```
25+
26+A `wind` is defined in `arvo.hoon` as:
27+
28+```hoon
29+++ wind
30+ |$ [a b]
31+ $% [%pass p=path q=a]
32+ [%slip p=a]
33+ [%give p=b]
34+ ==
35+```
36+
37+Gall will not accept a `%slip`, so we can ignore that. A `card`, then, is one
38+of:
39+
40+```hoon
41+[%pass path note]
42+[%give gift]
43+```
44+
45+We'll consider each separately.
46+
47+## `%pass`
48+
49+```hoon
50+[%pass path note]
51+```
52+
53+The purpose of a `%pass` card is to send some kind of one-off request, action,
54+task, or what have you, to another agent or vane. A `%pass` card is a request
55+your agent _initiates_. This is in contrast to a [`%give`](#give) card, which is
56+sent in _response_ to another agent or vane.
57+
58+The type of the first field in a `%pass` card is a `path`. A `path` is just a
59+list of `@ta`, with a syntax of `/foo/bar/baz`. When you `%pass` something to an
60+agent or vane, this field specifies the `wire` on which the response should
61+arrive. A `wire` has the exact same type as a `path` (`/foo/bar/baz`), the
62+`wire`/`path` distinction is merely to differentiate their uses. When the agent
63+or vane responds to your request, your agent will see the `wire` as well as the
64+response itself. Your agent can then check the `wire` and maybe do different
65+things depending on its content. Both the
66+[`wire`](/docs/userspace/gall-guide/types#wire) and
67+[`path`](/docs/userspace/gall-guide/types#path) types are are covered in the
68+[types reference](/docs/userspace/gall-guide/types). We'll show how `wire`s are
69+practically used later on.
70+
71+The type of the next field is a `note:agent:gall` (henceforth just `note`), which
72+`lull.hoon` defines as:
73+
74+```hoon
75++$ note
76+ $% [%agent [=ship name=term] =task]
77+ [%arvo note-arvo]
78+ [%pyre =tang]
79+ ==
80+```
81+
82+- An `%agent` `note` is a request to another Gall agent, either local or on a
83+ remote ship. The `ship` and `name` fields are just the target ship and agent
84+ name. The `task` is the request itself, we'll discuss it separately
85+ [below](#task).
86+- An `%arvo` `note` is a request to a vane. We'll discuss such requests
87+ [below](#note-arvo).
88+- A `%pyre` `note` is XX TODO
89+
90+### `task`
91+
92+A `task:agent:gall` (henceforth just `task`) is defined in `lull.hoon` as:
93+
94+```hoon
95++$ task
96+ $% [%watch =path]
97+ [%watch-as =mark =path]
98+ [%leave ~]
99+ [%poke =cage]
100+ [%poke-as =mark =cage]
101+ ==
102+```
103+
104+These can be divided into two categories:
105+
106+#### Subscriptions
107+
108+`%watch`, `%watch-as` and `%leave` all pertain to subscriptions.
109+
110+- `%watch`: A request to subscribe to the specified `path`. Once subscribed,
111+ your agent will receive any updates the other agent sends out on that `path`.
112+ You can subscribe more than once to the same `path`, but each subscription
113+ must have a separate `wire` specified at the beginning of the [`%pass`
114+ card](#pass).
115+- `%watch-as`: This is the same as `%watch`, except Gall will convert updates to
116+ the given `mark` before delivering them to your agent.
117+- `%leave`: Unsubscribe from something to which you previously subscribed. The
118+ subscription to cancel is determined by the `wire` at the beginning of the
119+ [`pass` card](#pass) rather than the subscription `path`, so its argument is
120+ just `~`.
121+
122+**Examples**
123+
124+```hoon
125+[%pass /some/wire %agent [~some-ship %some-agent] %watch /some/path]
126+[%pass /some/wire %agent [~some-ship %some-agent] %watch-as %some-mark /some/path]
127+[%pass /some/wire %agent [~some-ship %some-agent] %leave ~]
128+```
129+
130+#### Pokes
131+
132+Pokes are requests, actions, or just some data which you send to another agent.
133+Unlike subscriptions, these are just one-off messages.
134+
135+A `%poke` contains a `cage` of some data. A `cage` is a cell of `[mark vase]`.
136+The `mark` is just a `@tas` like `%foo`, and corresponds to a mark file in the
137+`/mar` directory. We'll cover marks in detail later, but you can refer to the
138+[`mark`](/docs/userspace/gall-guide/types#mark) entry in the type reference for
139+further details. The `vase` contains the actual data you're sending.
140+
141+The `%poke-as` task is the same as `%poke` except Gall will convert the `cage`
142+to the `mark` you specify before sending it off.
143+
144+**Examples**
145+
146+```hoon
147+[%pass /some/wire %agent [~some-ship %some-agent] %poke %some-mark !>('some data')]
148+[%pass /some/wire %agent [~some-ship %some-agent] %poke-as %mark-to-use %some-mark !>('some-data')]
149+```
150+
151+### `note-arvo`
152+
153+A `note-arvo` is defined in `lull.hoon` like so:
154+
155+```hoon
156++$ note-arvo
157+ $~ [%b %wake ~]
158+ $% [%a task:ames]
159+ [%b task:behn]
160+ [%c task:clay]
161+ [%d task:dill]
162+ [%e task:eyre]
163+ [%g task:gall]
164+ [%i task:iris]
165+ [%j task:jael]
166+ [%$ %whiz ~]
167+ [@tas %meta vase]
168+ ==
169+```
170+
171+The letter at the beginning corresponds to the vane - `%b` for Behn, `%c` for
172+Clay, etc. After then vane letter comes the task. Each vane has an API with a
173+set of tasks that it will accept, and are defined in each vane's section of
174+`lull.hoon`. Each vane's tasks are documented on the API Reference page of its
175+section in the [Arvo documentation](/docs/arvo/arvo).
176+
177+#### Examples
178+
179+```hoon
180+[%pass /some/wire %arvo %b %wait (add ~m1 now.bowl)]
181+[%pass /some/wire %arvo %e %connect /some/url/path %some-agent]
182+```
183+
184+## `%give`
185+
186+```hoon
187+[%give gift]
188+```
189+
190+The purpose of a `%give` card is to respond to a request made by another agent
191+or vane. More specifically, it's either for acknowledging a request, or for
192+sending out updates to subscribers (which are technically in response to their
193+initial subscription request, however long ago it may have been). This is in
194+contrast to a [`%pass`](#give) card, which is essentially unsolicited.
195+
196+A `%give` card contains a `gift:agent:gall` (henceforth just `gift`), which is
197+defined in `lull.hoon` as:
198+
199+```hoon
200++$ gift
201+ $% [%fact paths=(list path) =cage]
202+ [%kick paths=(list path) ship=(unit ship)]
203+ [%watch-ack p=(unit tang)]
204+ [%poke-ack p=(unit tang)]
205+ ==
206+```
207+
208+These can be divided into two categories:
209+
210+### Acknowledgements
211+
212+`%watch-ack` and `%poke-ack` are sent in response to a `%watch` or `%poke`
213+request respectively. If the `(unit tang)` is null, it's an ack - a positive
214+acknowledgement. If the `(unit tang)` is non-null, it's a nack - a negative
215+acknowledgement, and the `tang` contains an error message. Gall automatically
216+sends a nack with a traceback if your agent crashes while processing the
217+request, and automatically sends an ack if it does not. Therefore, you would not explicitly produce a `%watch-ack` or `%poke-ack` gift.
218+
219+#### Examples
220+
221+```hoon
222+[%give %watch-ack `~[leaf+"foo" leaf+"bar"]]
223+[%give %poke-ack `~[leaf+"foo" leaf+"bar"]]
224+```
225+
226+### Subscriptions
227+
228+`%fact` and `%kick` are both sent out to existing subscribers - entities that
229+have previously successfully `%watch`ed a path on your ship.
230+
231+A `%kick` gift takes a list of `path`s, which are subscription paths, and a
232+`(unit ship)`, which is the ship to kick from those paths. If the `unit` is
233+null, all subscribers are kicked from the specified paths. Note that sometimes
234+Gall can produce `%kick` gifts without your agent explicitly sending a card, due
235+to networking conditions. Therefore, you should not assume `%kick`s you receive
236+are intentional, and should try resubscribing by default.
237+
238+`%fact` gifts are how updates are sent out to subscribers. The `paths` field is
239+a list of subscription paths - all subscribers of the specified `path`s will
240+receive the `%fact`. The `cage` is the data itself - a cell of a `mark` and a
241+`vase`.
242+
243+#### Examples
244+
245+```hoon
246+[%give %fact ~[/some/path /another] %some-mark !>('some data')]
247+[%give %kick ~[/some/path /another] `~some-ship]
248+```
249+
250+## Summary
251+
252+Here's a diagram that summarizes the different kinds of `card`s:
253+
254+[![card diagram](https://m.tinnus-napbus.xyz/pub/card-diagram.svg)](https://m.tinnus-napbus.xyz/pub/card-diagram.svg)
255+
256+## Exercises
257+
258+- Have a read of the [`wire`](/docs/userspace/gall-guide/types#wire) and
259+ [`path`](/docs/userspace/gall-guide/types#path) entries in the type reference.
content/docs/userspace/gall-guide/6-pokes.mdnew file+512
@@ -0,0 +1,512 @@
1++++
2+title = "6. Pokes"
3+weight = 30
4+template = "doc.html"
5++++
6+
7+In this lesson we'll look at sending and receiving one-off messages called
8+`%poke`s. We'll look at the `on-poke` agent arm which handles incoming pokes.
9+We'll also introduce the `on-agent` arm, and look at one kind of response it can
10+take - a `%poke-ack`.
11+
12+## Receiving a poke
13+
14+Whenever something tries to poke your agent, Gall calls your agent's `on-poke`
15+arm and give it the `cage` from the poke as its sample. The `on-poke` arm will
16+contain a gate that takes a `cage` and produces a `(quip card _this)` like so:
17+
18+```hoon
19+|= [=mark =vase]
20+^- (quip card _this)
21+...
22+```
23+
24+The sample of the gate is typically specified as a cell of `mark` and `vase`
25+rather than just `cage`, simply because it's easier to work with.
26+
27+Typically, you'd first test the `mark` with something like a
28+[wutlus](/docs/hoon/reference/rune/wut#-wutlus) `?+` expression, passing
29+unexpected `mark`s to `%default-agent`, which just crashes. We'll look at custom
30+`mark`s in a subsequent lesson, but the basic patten looks like:
31+
32+```hoon
33+?+ mark (on-poke:def mark vase)
34+ %noun ...
35+ %something-else ...
36+ ...
37+==
38+```
39+
40+After testing the `mark`, you'd typically extract the `vase` to the expected type, and then apply whatever logic you need. For example:
41+
42+```hoon
43+=/ action !<(some-type vase)
44+?- -.action
45+ %foo ...
46+ %bar ...
47+ ...
48+==
49+```
50+
51+Your agent will then produce a list of `card`s to be sent off and a new,
52+modified state, as appropriate. We'll go into subscriptions in the next lesson,
53+but just to give you an idea of a typical pattern: An agent for a chat app might
54+take new messages as pokes, add them to the list of messages in its state, and
55+send out the new messages to subscribed chat participants as `gift`s.
56+
57+As discussed [in the previous
58+lesson](/docs/userspace/gall-guide/5-cards#acknowledgements), Gall will
59+automatically send a `%poke-ack` `gift` back to wherever the poke came from. The
60+`%poke-ack` will be a nack if your agent crashed while processing the poke, and
61+an ack otherwise. If it's a nack, the `tang` in the `%poke-ack` will contain a
62+stack trace of the crash.
63+
64+As a result, you do not need to explicitly send a `%poke-ack`. Instead, you
65+would design your agent to handle only what you expect and crash in all other
66+cases. You can crash by passing the `cage` to `%default-agent`, or just with a
67+`!!`. In the latter case, if you want to add an error message to the stack
68+trace, you can do so like:
69+
70+```hoon
71+~| "some error message"
72+!!
73+```
74+
75+This will produce a trace that looks something like:
76+
77+```
78+/sys/vane/gall/hoon:<[1.372 9].[1.372 37]>
79+/app/pokeme/hoon:<[31 3].[43 5]>
80+/app/pokeme/hoon:<[32 3].[43 5]>
81+/app/pokeme/hoon:<[34 5].[42 7]>
82+/app/pokeme/hoon:<[35 5].[42 7]>
83+/app/pokeme/hoon:<[38 7].[41 27]>
84+/app/pokeme/hoon:<[39 9].[40 11]>
85+"some error message"
86+/app/pokeme/hoon:<[40 9].[40 11]>
87+```
88+
89+Note that the `tang` in the nack is just for debugging purposes, you should not
90+try to pass actual data by encoding it in the nack `tang`.
91+
92+## Sending a poke
93+
94+An agent can send pokes to other agents by producing [`%poke`
95+`card`s](/docs/userspace/gall-guide/5-cards#pokes). Any agent arm apart from
96+`on-peek` and `on-save` can produce such `card`s. The arms would typically
97+produce `card`(s) like so:
98+
99+```hoon
100+:_ this
101+:~ [%pass /some/wire %agent [~target-ship %target-agent] %poke %some-mark !>('some data')]
102+==
103+```
104+
105+The [colcab](/docs/hoon/reference/rune/col#_-colcab) (`:_`) rune makes an
106+inverted cell, it's just `:-` but with the head and tail swapped. We use colcab
107+to produce the `(quip card _this)` because the list of cards is typically
108+"heavier" than the new agent core expression (`this`), so it makes it more
109+readable.
110+
111+### Receiving the `%poke-ack`
112+
113+The pokes will be processed by their targets [as described in the previous
114+section](#receiving-a-poke), and they'll `%give` back a `%poke-ack` on the
115+`wire` you specified (`/some/wire` in the previous example). When Gall gets the
116+`%poke-ack` back, it will call the `on-agent` arm of your agent, with the `wire`
117+it came in on and the `%poke-ack` itself in a `sign:agent:gall`. Your `on-agent`
118+arm would therefore begin like so:
119+
120+```hoon
121+|= [=wire =sign:agent:gall]
122+^- (quip card _this)
123+...
124+```
125+
126+A `sign:agent:gall` (henceforth just `sign`) is defined in `lull.hoon` as:
127+
128+```hoon
129++$ sign
130+ $% [%poke-ack p=(unit tang)]
131+ [%watch-ack p=(unit tang)]
132+ [%fact =cage]
133+ [%kick ~]
134+ ==
135+```
136+
137+It's basically the same as a [`gift`](/docs/userspace/gall-guide/5-cards#give),
138+but incoming instead of outgoing.
139+
140+The simplest way to handle a `%poke-ack` by passing it to `%default-agent`'s
141+`on-agent` arm, which will just print an error message to the terminal if it's a
142+nack and otherwise do nothing. Sometimes, though, you'll want your agent to do
143+something different depending on whether the poke failed or succeeded (and
144+therefore whether it's a nack or an ack). In that case, you'd typically first test the `wire` so you can tell what the `%poke-ack` was for. You might do something like:
145+
146+```hoon
147+?+ wire (on-agent:def wire sign)
148+ [%some %wire ~] ...
149+ ...
150+==
151+```
152+
153+After that, you'll need to see what kind of `sign` it is:
154+
155+```hoon
156+?+ -.sign (on-agent:def wire sign)
157+ %poke-ack ...
158+ ...
159+```
160+
161+Then, you can tell whether it's an ack or a nack by testing whether the `(unit tang)` in the `%poke-ack` is null:
162+
163+```hoon
164+?~ p.sign
165+ ...(what to do if the poke succeeded)...
166+...(what to do if the poke failed)...
167+```
168+
169+Finally, you can produce any `card`s and modified agent state as appropriate and
170+return the `(quip card _this)`.
171+
172+## Example
173+
174+We're going to look at a couple of agents, to demonstrate both sending and receiving pokes. Here's the first, an agent that receives pokes:
175+
176+### `pokeme.hoon`
177+
178+```hoon
179+/+ default-agent, dbug
180+|%
181++$ versioned-state
182+ $% state-0
183+ ==
184++$ state-0 [%0 val=@ud]
185++$ card card:agent:gall
186+--
187+%- agent:dbug
188+=| state-0
189+=* state -
190+^- agent:gall
191+|_ =bowl:gall
192++* this .
193+ def ~(. (default-agent this %.n) bowl)
194+++ on-init
195+ ^- (quip card _this)
196+ `this
197+++ on-save
198+ ^- vase
199+ !>(state)
200+++ on-load
201+ |= old-state=vase
202+ ^- (quip card _this)
203+ =/ old !<(versioned-state old-state)
204+ ?- -.old
205+ %0 `this(state old)
206+ ==
207+++ on-poke
208+ |= [=mark =vase]
209+ ^- (quip card _this)
210+ ?+ mark (on-poke:def mark vase)
211+ %noun
212+ =/ action !<(?(%inc %dec) vase)
213+ ?- action
214+ %inc `this(val +(val))
215+ %dec
216+ ?: =(0 val)
217+ ~| "Can't decrement - already zero!"
218+ !!
219+ `this(val (dec val))
220+ ==
221+ ==
222+++ on-watch on-watch:def
223+++ on-leave on-leave:def
224+++ on-peek on-peek:def
225+++ on-agent on-agent:def
226+++ on-arvo on-arvo:def
227+++ on-fail on-fail:def
228+--
229+```
230+
231+This is a very simple agent that just has `val`, a number, in its state. It will
232+take pokes that either increment or decrement the number in its state. Here's its `on-poke` arm:
233+
234+```hoon
235+++ on-poke
236+ |= [=mark =vase]
237+ ^- (quip card _this)
238+ ?+ mark (on-poke:def mark vase)
239+ %noun
240+ =/ action !<(?(%inc %dec) vase)
241+ ?- action
242+ %inc `this(val +(val))
243+ %dec
244+ ?: =(0 val)
245+ ~| "Can't decrement - already zero!"
246+ !!
247+ `this(val (dec val))
248+ ==
249+ ==
250+```
251+
252+It only expects pokes with a `%noun` mark, and passes all others to
253+`on-poke:def`, which just crashes. For `%noun` pokes, it expects to receive
254+either `%inc` or `%dec` in the `vase`. If it's `%inc`, it produces a new `this`
255+with `val` incremented. If it's `%dec`, it produces `this` with `val`
256+decremented, or crashes if `val` is already zero.
257+
258+Let's try it out. Save the agent above as `/app/pokeme.hoon` in the `%base` desk
259+and `|commit %base`. Then, start it up with `|rein %base [& %pokeme]`. We can check its initial state with `dbug`:
260+
261+```
262+> 0
263+> :pokeme +dbug [%state %val]
264+>=
265+```
266+
267+Next, we'll try poking it. The dojo lets you poke agents with the following syntax:
268+
269+```
270+:agent-name &some-mark ['some' 'noun']
271+```
272+
273+If the `mark` part is omitted, it'll just default to `%noun`. Since our agent only takes a `%noun` mark, we can skip that. The rest will be packed in a vase by the dojo and delivered as a poke, so we can do:
274+
275+```
276+> :pokeme %inc
277+>=
278+```
279+
280+If we now look at the state with `dbug`, we'll see the poke was successful and it's been incremented:
281+
282+```
283+> 1
284+> :pokeme +dbug [%state %val]
285+>=
286+```
287+
288+Let's try decrement:
289+
290+```
291+> :pokeme %dec
292+>=
293+> 0
294+> :pokeme +dbug [%state %val]
295+>=
296+```
297+
298+As you can see, it's back at zero. If we try again, we'll see it fails, and the dojo will print the `tang` in the `%poke-ack` nack:
299+
300+```
301+> :pokeme %dec
302+/sys/vane/gall/hoon:<[1.372 9].[1.372 37]>
303+/app/pokeme/hoon:<[31 3].[43 5]>
304+/app/pokeme/hoon:<[32 3].[43 5]>
305+/app/pokeme/hoon:<[34 5].[42 7]>
306+/app/pokeme/hoon:<[35 5].[42 7]>
307+/app/pokeme/hoon:<[38 7].[41 27]>
308+/app/pokeme/hoon:<[39 9].[40 11]>
309+"Can't decrement - already zero!"
310+/app/pokeme/hoon:<[40 9].[40 11]>
311+dojo: app poke failed
312+```
313+
314+### `pokeit.hoon`
315+
316+Here's a second agent. It takes a poke of `%inc` or `%dec` like before, but
317+rather that updating its own state, it sends two pokes to `%pokeme`, so
318+`%pokeme`'s state will be incremented or decremented by two.
319+
320+```hoon
321+/+ default-agent, dbug
322+|%
323++$ versioned-state
324+ $% state-0
325+ ==
326++$ state-0 [%0 ~]
327++$ card card:agent:gall
328+--
329+%- agent:dbug
330+=| state-0
331+=* state -
332+^- agent:gall
333+|_ =bowl:gall
334++* this .
335+ def ~(. (default-agent this %.n) bowl)
336+++ on-init
337+ ^- (quip card _this)
338+ `this
339+++ on-save
340+ ^- vase
341+ !>(state)
342+++ on-load
343+ |= old-state=vase
344+ ^- (quip card _this)
345+ =/ old !<(versioned-state old-state)
346+ ?- -.old
347+ %0 `this(state old)
348+ ==
349+++ on-poke
350+ |= [=mark =vase]
351+ ^- (quip card _this)
352+ ?+ mark (on-poke:def mark vase)
353+ %noun
354+ =/ action !<(?(%inc %dec) vase)
355+ ?- action
356+ %inc
357+ :_ this
358+ :~ [%pass /inc %agent [our.bowl %pokeme] %poke %noun !>(%inc)]
359+ [%pass /inc %agent [our.bowl %pokeme] %poke %noun !>(%inc)]
360+ ==
361+ %dec
362+ :_ this
363+ :~ [%pass /dec %agent [our.bowl %pokeme] %poke %noun !>(%dec)]
364+ [%pass /dec %agent [our.bowl %pokeme] %poke %noun !>(%dec)]
365+ ==
366+ ==
367+ ==
368+++ on-watch on-watch:def
369+++ on-leave on-leave:def
370+++ on-peek on-peek:def
371+++ on-agent
372+ |= [=wire =sign:agent:gall]
373+ ^- (quip card _this)
374+ ?+ wire (on-agent wire sign)
375+ [%inc ~]
376+ ?. ?=(%poke-ack -.sign)
377+ (on-agent wire sign)
378+ ?~ p.sign
379+ %- (slog '%pokeit: Increment poke succeeded!' ~)
380+ `this
381+ %- (slog '%pokeit: Increment poke failed!' ~)
382+ `this
383+ ::
384+ [%dec ~]
385+ ?. ?=(%poke-ack -.sign)
386+ (on-agent wire sign)
387+ ?~ p.sign
388+ %- (slog '%pokeit: Decrement poke succeeded!' ~)
389+ `this
390+ %- (slog '%pokeit: Decrement poke failed!' ~)
391+ `this
392+ ==
393+++ on-arvo on-arvo:def
394+++ on-fail on-fail:def
395+--
396+```
397+
398+Here's the `on-poke` arm:
399+
400+```hoon
401+++ on-poke
402+ |= [=mark =vase]
403+ ^- (quip card _this)
404+ ?+ mark (on-poke:def mark vase)
405+ %noun
406+ =/ action !<(?(%inc %dec) vase)
407+ ?- action
408+ %inc
409+ :_ this
410+ :~ [%pass /inc %agent [our.bowl %pokeme] %poke %noun !>(%inc)]
411+ [%pass /inc %agent [our.bowl %pokeme] %poke %noun !>(%inc)]
412+ ==
413+ %dec
414+ :_ this
415+ :~ [%pass /dec %agent [our.bowl %pokeme] %poke %noun !>(%dec)]
416+ [%pass /dec %agent [our.bowl %pokeme] %poke %noun !>(%dec)]
417+ ==
418+ ==
419+ ==
420+```
421+
422+It's similar to `%pokeme`, except it sends two `%poke` `card`s to `%pokeme` for
423+each case. The `%inc` pokes specify a `wire` of `/inc`, and the `%dec` pokes
424+specify a `wire` of `/dec`, so we can differentiate the responses. It also has
425+the following `on-agent`:
426+
427+```hoon
428+++ on-agent
429+ |= [=wire =sign:agent:gall]
430+ ^- (quip card _this)
431+ ?+ wire (on-agent wire sign)
432+ [%inc ~]
433+ ?. ?=(%poke-ack -.sign)
434+ (on-agent wire sign)
435+ ?~ p.sign
436+ %- (slog '%pokeit: Increment poke succeeded!' ~)
437+ `this
438+ %- (slog '%pokeit: Increment poke failed!' ~)
439+ `this
440+ ::
441+ [%dec ~]
442+ ?. ?=(%poke-ack -.sign)
443+ (on-agent wire sign)
444+ ?~ p.sign
445+ %- (slog '%pokeit: Decrement poke succeeded!' ~)
446+ `this
447+ %- (slog '%pokeit: Decrement poke failed!' ~)
448+ `this
449+ ==
450+```
451+
452+`on-agent` tests the `wire`, checks if it's a `%poke-ack`, and then prints to
453+the terminal whether it succeeded or failed.
454+
455+Save this agent to `/app/pokeit.hoon` on the `%base` desk, `|commit %base`, and start it with `|rein %base [& %pokeme] [& %pokeit]`.
456+
457+Let's try it out:
458+
459+```
460+%pokeit: Increment poke succeeded!
461+%pokeit: Increment poke succeeded!
462+> :pokeit %inc
463+>=
464+```
465+
466+`%pokeit` has received positive `%poke-ack`s, which means both pokes succeeded.
467+It could tell they were increments because the `%poke-ack`s came back on the
468+`/inc` path we specified. We can check the state of `%pokeme` to confirm:
469+
470+```
471+> 2
472+> :pokeme +dbug [%state %val]
473+>=
474+```
475+
476+Let's try decrementing `%pokeme` so it's an odd number, and then try a `%dec` via `%pokeit`:
477+
478+```
479+> :pokeme %dec
480+>=
481+%pokeit: Decrement poke succeeded!
482+%pokeit: Decrement poke failed!
483+> :pokeit %dec
484+>=
485+```
486+
487+The `on-agent` arm of `%pokeit` has received one ack and one nack. The first
488+took `val` to zero, and the second crashed trying to decrement below zero.
489+
490+## Summary
491+
492+- Incoming pokes go to the `on-poke` arm of an agent.
493+- The `on-poke` arm takes a `cage` and produces an `(quip card _this)`.
494+- Gall will automatically return a `%poke-ack` to the poke's source, with a
495+ stack trace in the `(unit tang)` if your agent crashed while processing the
496+ poke.
497+- Outgoing pokes can be sent by including `%poke` `%pass` `card`s in the `quip`
498+ produced by most agent arms.
499+- `%poke-ack`s in response to pokes you've sent will come in to the `on-agent`
500+ arm in a `sign`, on the `wire` you specified in the original `%poke` `card`.
501+- You can poke agents from the dojo with a syntax of `:agent &mark ['some' 'noun']`.
502+
503+## Exercises
504+
505+- Run through the [Example](#example) yourself on a fake ship if you've not done
506+ so already.
507+- Have a look at the `on-agent` arm of `/lib/default-agent.hoon` to see how
508+ `%default-agent` handles incoming `sign`s.
509+- Try modifying the `%pokeme` agent with another action of your choice (in
510+ addition to `%inc` and `%dec`).
511+- Try modifying the `%pokeit` agent to send your new type of poke to `%pokeme`,
512+ and handle the `%poke-ack` it gets back.
content/docs/userspace/gall-guide/7-sur-and-marks.mdnew file+373
@@ -0,0 +1,373 @@
1++++
2+title = "7. Structures and Marks"
3+weight = 35
4+template = "doc.html"
5++++
6+
7+Before we get into subscription mechanics, there's three things we need to touch
8+on that are very commonly used in Gall agents. The first is defining an agent's
9+types in a `/sur` structure file, the second is `mark` files, and the third is
10+permissions.
11+
12+## `/sur`
13+
14+In the [previous lesson on pokes](/docs/userspace/gall-guide/6-pokes), we used a
15+very simple union in the `vase` for incoming pokes:
16+
17+```hoon
18+=/ action !<(?(%inc %dec) vase)
19+```
20+
21+A real Gall agent, however, is likely to have a more complicated API. The most
22+common approach is to define a head-tagged union of all possible poke types the
23+agent will accept, and another for all possible updates it might send out to
24+subscribers. Rather than defining these types in the agent itself, you would
25+typically define them in a separate core saved in the `/sur` directory of the
26+desk. The `/sur` directory is short for "**s**truct**ur**es", and is the
27+canonical location for userspace type definitions.
28+
29+With this approach, your agent can simply import the structure file and make use
30+of its types. Additionally, if someone else wants to write an agent that
31+interfaces with yours, they can simply include your structure file in their own
32+desk and easily interface with your agent's API.
33+
34+#### Example
35+
36+Let's look at a practical example. If we were creating a simple To-Do app, our
37+agent might accept a few possible `action`s as pokes: Adding a new task,
38+deleting a task, toggling a task's "done" status, and renaming an existing task.
39+It might also be able to send `update`s out to subscribers when these events
40+occur. If our agent were named `%todo`, it might have the following structure in
41+`/sur/todo.hoon`:
42+
43+```hoon
44+|%
45++$ id @
46++$ name @t
47++$ task [=name done=?]
48++$ tasks (map id task)
49++$ action
50+ $% [%add =name]
51+ [%del =id]
52+ [%toggle =id]
53+ [%rename =id =name]
54+ ==
55++$ update
56+ $% [%add =id =name]
57+ [%del =id]
58+ [%toggle =id]
59+ [%rename =id =name]
60+ [%initial =tasks]
61+ ==
62+--
63+```
64+
65+Our `%todo` agent could then import this structure file with a [fashep ford
66+rune](/docs/arvo/ford/ford#ford-runes) (`/-`) at the beginning of the agent like
67+so:
68+
69+```hoon
70+/- todo
71+```
72+
73+The agent's state could be defined like:
74+
75+```hoon
76+|%
77++$ versioned-state
78+ $% state-0
79+ ==
80++$ state-0 [%0 =tasks:todo]
81++$ card card:agent:gall
82+--
83+```
84+
85+Then, in its `on-poke` arm, it could handle these actions in the following
86+manner:
87+
88+```hoon
89+++ on-poke
90+ |= [=mark =vase]
91+ |^ ^- (quip card _this)
92+ ?+ mark (on-poke:def mark vase)
93+ %noun
94+ =^ cards state
95+ (handle-poke !<(action:todo vase))
96+ [cards this]
97+ ++ handle-poke
98+ |= =action:todo
99+ ^- (quip card _state)
100+ ?- -.action
101+ %add
102+ :_ state(tasks (~(put by tasks) now.bowl [name.action %.n]))
103+ :~ [%give %fact ~[/updates] %noun !>(`update:todo`[%add now.bowl name.action])]
104+ ==
105+ ::
106+ %del
107+ :_ state(tasks (~(del by tasks) id.action))
108+ :~ [%give %fact ~[/updates] %noun !>(`update:todo`action)]
109+ ==
110+ ::
111+ %toggle
112+ :_ state(tasks (~(jab by tasks) id.action |=(=task task(done !done.task))))
113+ :~ [%give %fact ~[/updates] %noun !>(`update:todo`action)]
114+ ==
115+ ::
116+ %rename
117+ :_ state(tasks (~(jab by tasks) id.action |=(=task task(name name.action))))
118+ :~ [%give %fact ~[/updates] %noun !>(`update:todo`action)]
119+ ==
120+ ==
121+ --
122+```
123+
124+Let's break this down a bit. Firstly, our `on-poke` arm includes a
125+[barket](/docs/hoon/reference/rune/bar#-barket) (`|^`) rune. Barket creates a
126+core with a `$` arm that's computed immediately. We extract the `vase` to the
127+`action:todo` type and immediately pass it to the `handle-poke` arm of the core
128+created with the barket. This `handle-poke` arm tests what kind of `action` it's
129+received by checking its head, updates the state, and also sends an update to
130+subscribers, as appropriate. Don't worry too much about the `%give` `card` for
131+now - we'll cover subscriptions in the next lesson.
132+
133+Notice that the `handle-poke` arm produces a `(quip card _state)` rather than
134+`(quip card _this)`. The call to `handle-poke` is also part of the following
135+expression:
136+
137+```hoon
138+=^ cards state
139+ (handle-poke !<(action:todo vase))
140+[cards this]
141+```
142+
143+The [tisket](/docs/hoon/reference/rune/tis#-tisket) (`=^`) expression takes two
144+arguments: A new named noun to pin to the subject (`cards` in this case), and an
145+existing wing of the subject to modify (`state` in this case). Since
146+`handle-poke` produces `(quip card _state)`, we're saving the `card`s it
147+produces to `cards` and replacing the existing `state` with its new one.
148+Finally, we produce `[cards this]`, where `this` will now contain the modified
149+`state`. The `[cards this]` is a `(quip card _this)`, which our `on-poke` arm is
150+expected to produce.
151+
152+This might seem a little convoluted, but it's a common pattern we do for two
153+reasons. Firstly, it's not ideal to be passing around the entire `this` agent
154+core - it's much tidier just passing around the `state`, until you actually want
155+to return it to Gall. Secondly, It's much easier to read when the poke handling
156+logic is separated into its own arm. This is a fairly simple example but if your
157+agent is more complex, handling multiple `mark`s and containing additional logic
158+before it gets to the actual contents of the `vase`, structuring things this way
159+can be useful.
160+
161+You can of course structure your `on-poke` arm differently than we've done
162+here - we're just demonstrating a typical pattern.
163+
164+## `mark` files
165+
166+So far we've just used a `%noun` mark for pokes - we haven't really delved into
167+what such `mark`s represent, or considered writing custom ones.
168+
169+Formally, marks are file types in the Clay filesystem. They correspond to mark
170+files in the `/mar` directory of a desk. The `%noun` mark, for example,
171+corresponds to the `/mar/noun.hoon` file. Mark files define the actual hoon data type for the file (e.g. a `*` noun for the `%noun` mark), but they also specify some extra things:
172+
173+- Methods for converting between the mark in question and other marks.
174+- Revision control functions like patching, diffing, merging, etc.
175+
176+Aside from their use by Clay for storing files in the filesystem, they're also
177+used extensively for exchanging data with the outside world, and for exchanging
178+data between Gall agents. When data comes in from a remote ship, destined for a
179+particular Gall agent, it will be validated by the local mark file in `/mar`
180+which corresponds to its `mark` before being delivered to the agent. If the
181+remote data has no corresponding mark in `/mar` or it fails validation, it will
182+crash before it touches the agent.
183+
184+A mark file is a `door` with three arms. The door's sample is the data type that
185+particular mark will handle. For example, the sample of the `%noun` mark is just
186+`non=*`, since it handles any noun. The three arms are as follows:
187+
188+- `grab`: Methods for converting _to_ our mark _from_ other marks.
189+- `grow`: Methods for converting _from_ our mark _to_ other marks.
190+- `grad`: Revision control functions.
191+
192+In the context of Gall agents, you'll likely just use marks for sending and
193+receiving data, and not for actually storing files in Clay. Therefore, it's
194+unlikely you'll need to write custom revision control functions in the `grad`
195+arm for marks you use in your agent. Instead, you can simply delegate `grad`
196+functions to another mark - typically `%noun`. If you want to learn more about
197+writing such `grad` functions, you can refer to the [Marks
198+Guide](/docs/arvo/clay/marks/marks) in the Clay vane documentation, which is
199+much more comprehensive, but it's not necessary for our purposes here.
200+
201+#### Example
202+
203+Here's a very simple mark file for the `action` structure we created in the
204+[previous section](sur):
205+
206+```hoon
207+/- todo
208+|_ =action:todo
209+++ grab
210+ |%
211+ ++ noun action:todo
212+ --
213+++ grow
214+ |%
215+ ++ noun action
216+ --
217+++ grad %noun
218+--
219+```
220+
221+We've imported the `/sur/todo.hoon` structure library from the previous section,
222+and we've defined the sample of the `door` as `=action:todo`, since that's what
223+it will handle. Now let's consider the arms:
224+
225+- `grab`: This handles convertion methods _to_ our mark. It contains a core with
226+ arm names corresponding to other marks. In this case, it can only convert from
227+ a `noun` mark, so that's the core's only arm. The `noun` arm simply calls the
228+ `action` structure from our structure library. This is called "clamming" or
229+ "molding" - when some noun comes in, it gets called like `(action:todo [some-noun])` - producing data of the `action` type if it nests, and crashing
230+ otherwise.
231+- `grow`: This handles conversion methods _from_ our mark. Like `grab`, it
232+ contains a core with arm names corresponding to other marks. Here we've also
233+ only added an arm for a `%noun` mark. In this case, `action` data will come in
234+ as the sample of our `door`, and the `noun` arm simply returns its, since it's
235+ already a noun (as everything is in Hoon).
236+- `grad`: This is the revision control arm, and as you can see we've simply
237+ delegated such functions to the `%noun` mark.
238+
239+This mark file could be saved as `/mar/todo/action.hoon`, and then the `on-poke`
240+arm in the previous example could test for it instead of `%noun` like so:
241+
242+```hoon
243+++ on-poke
244+ |= [=mark =vase]
245+ |^ ^- (quip card _this)
246+ ?+ mark (on-poke:def mark vase)
247+ %todo-action
248+ ...
249+```
250+
251+Note how `%todo-action` will be resolved to `/mar/todo/action.hoon` - the hyphen
252+will be interpreted as `/` if there's not already `/mar/todo-action.hoon`.
253+
254+This simple mark file isn't all that useful. Typically, you'd add `json` arms to
255+`grow` and `grab`, which allow your data to be converted to and from JSON, and
256+therefore allow your agent to communicate with a web front-end. Front-ends,
257+JSON, and Eyre's APIs which facilitate such communications will be covered in
258+part two of the Gall guide. For now though, it's still useful to use marks and
259+understand how they work.
260+
261+One further note on marks - while data from remote ships must have a matching
262+mark file in `/mar`, it's possible to exchange data between local agents with
263+"fake" marks - ones that don't exist in `/mar`. Your `on-poke` arm could, for
264+example, use a made-up mark like `%foobar` for actions initiated locally.
265+
266+## Permissions
267+
268+In example agents so far, we haven't bothered to check where events such as
269+pokes are actually coming from - our example agents would accept data from
270+anywhere, including random foreign ships. We'll now have a look at how to handle
271+such permission checks.
272+
273+The `bowl` provided as the sample of an agent core includes a couple of useful
274+fields: `our` and `src`. The `our` field just contains the `@p` of the local
275+ship. The `src` field contains the `@p` of the ship from which the event
276+originated.
277+
278+When messages come in over Ames from other ships on the network, they're
279+encrypted with our ship's public keys and signed by the ship which sent them.
280+The Ames vane decrypts and verifies the messages using keys in the Jael vane,
281+which are obtained from the Azimuth Ethereum contract where Urbit ID ownership
282+and keys are recorded. This means the originating `@p` of all messages are
283+cryptographically validated before being passed on to Gall, so the `@p`
284+specified in the `src` field of the `bowl` can be trusted to be correct, and
285+checking permissions are very simple.
286+
287+You're free to use whatever logic you want for this, but the most common way is
288+to use [wutgar](/docs/hoon/reference/rune/wut#-wutgar) (`?>`) and
289+[wutgal](/docs/hoon/reference/rune/wut#-wutgal) (`?<`) runes, which are
290+respectively True and False assertions that crash if they don't evaluate to the
291+expected truth value. To only allow messages from the local ship, you can just
292+do the following in the relevant agent arm:
293+
294+```hoon
295+?> =(src.bowl our.bowl)
296+```
297+
298+A common permission is to allow messages from the local ship, as well as all of
299+its moons, which can be done with the `team:title` standard library function:
300+
301+```hoon
302+?> (team:title our.bowl src.bowl)
303+```
304+
305+If we want to only allow messages from a particular set of ships, we could, for
306+example, have a `(set @p)` in our agent's state called `allowed`. Then, we can
307+use the `has:in` set function to check:
308+
309+```hoon
310+?> (~(has in allowed) src.bowl)
311+```
312+
313+If we wanted to check a ship was allowed in a particular group in the Groups
314+app, we could scry our ship's `%group-store` agent and compare:
315+
316+```hoon
317+?> .^(? %gx /(scot %p our.bowl)/group-store/(scot %da now.bowl)/groups/ship/~bitbet-bolbel/urbit-community/join/(scot %p src.bowl)/noun)
318+```
319+
320+There are many ways to handle permissions, it all depends on your particular use
321+case.
322+
323+## Summary
324+
325+Type definitions:
326+
327+- An agent's type definitions live in the `/sur` directory of a desk.
328+- The `/sur` file is a core, typically containing a number of lusbuc (`+$`)
329+ arms.
330+- `/sur` files can be imported with the fashep (`/-`) Ford rune at the beginning
331+ of a file.
332+- Agent API types, for pokes and updates to subscribers, are commonly defined as
333+ head-tagged unions.
334+
335+Mark files:
336+
337+- Mark files live in the `/mar` directory of a desk.
338+- A `mark` like `%foo` corresponds to a file in `/mar` like `/mar/foo.hoon`
339+- Marks are file types in Clay, but are also used for passing data between
340+ agents as well as for external data generally.
341+- A mark file is a `door` with a sample of the data type it handles and three arms: `grab`, `grow` and `grad`.
342+- `grab` and `grow` each contain a core with arm names corresponding to other marks.
343+- `grab` and `grow` define functions for converting to and from our mark,
344+ respectively.
345+- `grad` defines revision control functions for Clay, but you'd typically just
346+ delegate such functions to the `%noun` mark.
347+- Incoming data from remote ships will have their marks validated by the
348+ corresponding mark file in `/mar`.
349+- Messages passed between agents on a local ship don't necessarily need mark
350+ files in `/mar`.
351+- Mark files are most commonly used for converting an agent's native types to
352+ JSON, in order to interact with a web front-end (which we'll cover in part two
353+ of the Gall guide).
354+
355+Permissions:
356+
357+- The source of incoming messages from remote ships are cryptographically
358+ validated by Ames and provided to Gall, which then populates the `src` field
359+ of the `bowl` with the `@p`.
360+- Permissions are most commonly enforced with wutgar (`?>`) and wutgal (`?<`)
361+ assertions in the relevant agent arms.
362+- Messages can be restricted to the local ship with `=(src.bowl our.bowl)` or to
363+ its moons as well with `(team:title our.bowl src.bowl)`.
364+- There are many other ways to handle permissions, it just depends on the needs
365+ of the particular agent.
366+
367+## Exercises
368+
369+- Have a quick look at the [tisket
370+ documentation](/docs/hoon/reference/rune/tis#-tisket).
371+- Try writing a mark file for the `update:todo` type, in a similar fashion to
372+ the `action:todo` one in the [mark file section](#mark-file). You can compare
373+ yours to the one we'll use in the next lesson.
content/docs/userspace/gall-guide/8-subscriptions.mdnew file+834
@@ -0,0 +1,834 @@
1++++
2+title = "8. Subscriptions"
3+weight = 40
4+template = "doc.html"
5++++
6+
7+In this lesson we're going to look at subscriptions. Subscriptions are probably
8+the most complicated part of writing agents, so there's a fair bit to cover.
9+
10+## Incoming subscriptions
11+
12+Subscription requests from other entities arrive in your agent's `on-watch` arm.
13+The `on-watch` arm takes the `path` to which they're subscribing, and produces a
14+`(quip card _this)`:
15+
16+```hoon
17+++ on-watch
18+ |= =path
19+ ^- (quip card _this)
20+ ...
21+```
22+
23+Your agent's subscription paths would be defined in this arm, typically in a
24+wutlus (`?+`) expression or similar:
25+
26+```hoon
27+?+ path (on-watch:def path)
28+ [%updates ~]
29+ ......
30+ ......
31+ [%blah %blah ~]
32+ ......
33+ ......
34+ [%foo @ ~]
35+ =/ when=@da (slav %da i.t.path)
36+ ......
37+ ......
38+ [%bar %baz *]
39+ ?+ t.t.path (on-watch:def path)
40+ ~ .....
41+ [%abc %def ~] .....
42+ [%blah ~] .....
43+ ==
44+==
45+```
46+
47+Subscription paths can be simple and fixed like the first two examples above:
48+`/updates` and `/blah/blah`. They can also contain "wildcard" elements, with an
49+atom of a particular aura encoded in an element of the `path`, as in the `[%foo @ ~]` example. The type pattern matcher is quite limited, so we just specify
50+such variable elements as `@`, and then decode them with something like `(slav %da i.t.path)` (for a `@da`), as in the example. The incoming `path` in this
51+example would look like `/foo/~2021.11.14..13.30.39..6b17`. For more information
52+on decoding atoms in strings, see the [Strings
53+Guide](/docs/hoon/guides/strings#decoding-from-text).
54+
55+In the last case of `[%bar baz *]`, we're allowing a variable number of elements
56+in the path. First we check it's `/foo/bar/...something...`, and then we check
57+what the "something" is in another wutlus expression and handle it
58+appropriately. In this case, it could be `/foo/bar`, `/foo/bar/abc/def`, or
59+`/foo/bar/blah`. You could of course also have "wildcard" elements here too, so
60+there's not really a limit to the complexity of your subscription paths, or the
61+data that might be encoded therein.
62+
63+Permissions can be checked as described in the previous lesson, comparing the
64+source `@p` of the request in `src.bowl` to `our.bowl` or any other logic you
65+find appropriate.
66+
67+If a permission check fails, the path is not valid, or any other reason you want
68+to reject the subscription request, your agent can simply crash. The behavior
69+here is the same as with `on-poke` - Gall will send a `%watch-ack` card in
70+response, which is either an ack (positive acknowledgement) or a nack (negative
71+acknowledgement). The `(unit tang)` in the `%watch-ack` will be null if
72+processing succeeded, and non-null if it crashed, with a stack trace in the
73+`tang`. Like with `poke-ack`s, you don't need to explicitly send a
74+`%watch-ack` - Gall will do it implicitly.
75+
76+As well as sending a `%watch-ack`, Gall will also record the subscription in the
77+`sup` field of the `bowl`, if it succeeded. Then, when you send updates out to
78+subscribers of the `path` in question, the new subscriber will begin receiving
79+them as well.
80+
81+Updates to subscribers would usually be sent from other arms, but there's one
82+special case for `on-watch` which is very useful. Normally updates can only be
83+sent to all subscribers of a particular path - you can't target a specific
84+subscriber. There's one exception to this: In `on-watch`, when there's a new
85+subscription, you can send a `%fact` back with a null `(list path)`, and it'll
86+only go to the new subscriber. This is most useful when you want to give the
87+subscriber some initial state, which you otherwise couldn't do without sending
88+it to everyone. It might look something like this:
89+
90+```hoon
91+:_ this
92+:~ [%give %fact ~ %todo-update !>(`update:todo`initial+tasks)]
93+==
94+```
95+
96+## Sending updates to subscribers
97+
98+Once your agent has subscribers, it's easy to send them out updates. All you
99+need to do is produce `card`s with `%fact`s in them:
100+
101+```hoon
102+:_ this
103+:~ [%give %fact ~[/some/path /another/path] %some-mark !>('some data')]
104+ [%give %fact ~[/some/path] %some-mark !>('more data')]
105+ ....
106+==
107+```
108+
109+The `(list path)` in the `%fact` specifies which subscription `path`s to which
110+the `%fact` should be sent. All subscribers of all `path`s specified will
111+receive the `%fact`. Any agent arm which produces a `(quip card _this)` can send
112+`%fact`s to subscribers. Most often they will be produced in the `on-poke` arm,
113+since new data will often be added in `poke`s.
114+
115+## Kicking subscribers
116+
117+To kick a subscriber, you just send a `%kick` `card`:
118+
119+```hoon
120+[%give %kick ~[/some/path] `~sampel-palnet]
121+```
122+
123+The `(list path)` specifies which subscription `path`s the ship should be kicked
124+from, and the `(unit ship)` specifies which ship to kick. The `(unit ship)` can also be null, like so:
125+
126+```hoon
127+[%give %kick ~[/some/path] ~]
128+```
129+
130+In this case, all subscribers to the specified `path`s will be kicked.
131+
132+Note that `%kick`s are not exclusively sent by the agent itself - Gall can also
133+automatically kick subscribers under certain network conditions. Because of
134+this, `%kick`s are not typically interpreted as intentional, and the usual
135+behavior for a kicked agent is to try and resubscribe. Therefore, if you want to
136+disallow a particular subscriber, your agent's `on-watch` arm should reject
137+further subscription requests from them - your agent should not just `%kick`
138+them and call it a day.
139+
140+## Outgoing subscriptions
141+
142+Now that we've covered incoming subscriptions, we'll look at the other side of
143+it: Subscribing to other agents. This is done by `%pass`ing the target agent a
144+`%watch` task in a `card`:
145+
146+```hoon
147+[%pass /some/wire %agent [~some-ship %some-agent] %watch /some/path]
148+```
149+
150+If yor agent's subscription request is successful, updates will come in to your
151+agent's `on-agent` arm on the `wire` (`/some/wire` in this example) specified.
152+The `wire` can be anything you like - its purpose is for your agent to figure
153+out which subscription the updates are for. The `[ship term]` pair specifies the
154+ship and agent you're trying to subscribe to, and the final `path` (`/some/path`
155+in this example) is the subscription path to which you want to to subscribe - a
156+`path` the target agent has defined in its `on-watch` arm.
157+
158+Gall will deliver the `card` to the target agent and call that agent's
159+`on-watch` arm, which will process the request [as described
160+above](#incoming-subscription-requests), accept or reject it, and send back
161+either a positive or negative `%watch-ack`. The `%watch-ack` will come back in to your agent's `on-agent` arm in a `sign`, along with the `wire` you specified (`/some/wire` in this example):
162+
163+```hoon
164+++ on-agent
165+ |= [=wire =sign:agent:gall]
166+ ^- (quip card _this)
167+ .....
168+```
169+
170+The `sign` will be of the following format:
171+
172+```hoon
173+[%watch-ack p=(unit tang)]
174+```
175+
176+How you want to handle the `%watch-ack` really depends on the particular agent. In the simplest case, you can just pass it to the `on-agent` arm of `%default-agent`:
177+
178+```hoon
179+++ on-agent on-agent:def
180+```
181+
182+`%default-agent` will just accept it and do nothing apart from printing the
183+error in the `%watch-ack` `tang` if it's a nack. You shouldn't have your agent
184+crash on a `%watch-ack` - even if it's a nack your agent should process it
185+successfully. If you wanted to apply some additional logic on receipt of the
186+`%watch-ack`, you'd typically first test the `wire`, then test whether it's a
187+`%watch-ack`, then test whether it's an ack or a nack and do whatever's
188+appropriate:
189+
190+```hoon
191+++ on-agent
192+ |= [=wire =sign:agent:gall]
193+ ^- (quip card _this)
194+ ?+ wire (on-watch:def wire sign)
195+ [%expected %wire ~]
196+ ?+ -.sign (on-watch:def wire sign)
197+ %watch-ack
198+ ?~ p.sign
199+ ...(do something if ack)...
200+ ...(do something if nack)...
201+ ......
202+```
203+
204+The `on-agent` arm produces a `(quip card _this)`, so you can produce new
205+`card`s and update your agent's state, as appropriate.
206+
207+One further thing to note with subscriptions is that you can subscribe multiple
208+times to the same `path` on the same ship and agent, as long as the `wire` is
209+unique. If the ship, agent, `path` and `wire` are all the same as an existing
210+subscription, Gall will not allow the request to be sent, and instead fail with
211+an error message fed into the `on-fail` arm of your agent.
212+
213+## Receiving updates
214+
215+Assuming the `%watch` succeeded, your agent will now begin receiving any
216+`%fact`s the agent to which you've subscribed publishes on the path to which
217+you've subscribed. These `%fact`s will also come in to your agent's `on-agent`
218+arm in a `sign`, just like the initial `%watch-ack`. The `%fact` `sign` will
219+have the following format:
220+
221+```hoon
222+[%fact =cage]
223+```
224+
225+You would typically handle such `%fact`s in the following manner: Test the
226+`wire`, test whether the `sign` is a `%fact`, test the `mark` in the `cage`,
227+extract the data from the `vase` in the `cage`, and apply your logic. For example:
228+
229+```hoon
230+++ on-agent
231+ |= [=wire =sign:agent:gall]
232+ ^- (quip card _this)
233+ ?+ wire (on-watch:def wire sign)
234+ [%expected %wire ~]
235+ ?+ -.sign (on-watch:def wire sign)
236+ %fact
237+ ?+ p.cage.sign (on-watch:def wire sign)
238+ %expected-mark
239+ =/ foo !<(expected-type q.cage.sign)
240+ .....
241+ ......
242+```
243+
244+Note that Gall will not allow `sign`s to come into `on-agent` unsolicited, so
245+you don't necessarily need to include permission logic in this arm.
246+
247+The `on-agent` arm produces a `(quip card _this)`, so you can produce new
248+`card`s and update your agent's state, as appropriate.
249+
250+## Getting kicked
251+
252+For whatever reason, the agent you're `%watch`ing might what to kick your agent
253+from a `path` to which it's suscribed, ending your subscription and ceasing to
254+send your agent `%fact`s. To do this, it will send your agent a `%kick` card [as
255+described above](#kicking-subscribers). The `%kick` will come in to your agent's
256+`on-agent` arm in a `sign`, like `%watch-ack`s and `%fact`s do. The `%kick`
257+`sign` will have the following format:
258+
259+```hoon
260+[%kick ~]
261+```
262+
263+Since the `%kick` itself contains no information, you'll need to consider the
264+`wire` it comes in on to know what it pertains to. As explained previously,
265+`%kick`s aren't always intentional - sometimes Gall will kick subscribers due to
266+network issues. Your `on-agent` arm therefore has no way to know whether the
267+other agent actually intended to kick it. This means _your agent should almost
268+always try to resubscribe if it gets kicked_. Then, if the resubscribe `%watch`
269+request is rejected with a negative `%watch-ack`, you can conclude that it was
270+intentional and give up. The logic would look something like this:
271+
272+```hoon
273+++ on-agent
274+ |= [=wire =sign:agent:gall]
275+ ^- (quip card _this)
276+ ?+ wire (on-agent:def wire sign)
277+ [%some %wire ~]
278+ ?+ -.sign (on-agent:def wire sign)
279+ %kick
280+ :_ this
281+ :~ [%pass /some/wire %agent [src.bowl dap.bowl] %watch /some/path]
282+ ==
283+ .......
284+```
285+
286+## Leaving a subscription
287+
288+Eventually you may wish to unsubscribe from a `path` in another agent and stop
289+receiving updates. This is done by `%pass`ing a `%leave` task to the agent in
290+question:
291+
292+```hoon
293+[%pass /some/wire %agent [~some-ship %some-agent] %leave ~]
294+```
295+
296+The subcription to be ended is determined by the combination of the `wire`, ship
297+and agent, so the `%leave` task itself always just has `~` at the end.
298+
299+## Example
300+
301+Here we're going to give a pretty well fleshed out example. It will demonstrate
302+both inbound and outbound subscriptions, most of the concepts we've discussed
303+here, as well as some from the previous lesson - `/sur` files, `mark` files, and
304+permission checks.
305+
306+In previous lessons we've only dealt with things on a local ship - this example
307+will demonstrate messages being sent over the network.
308+
309+The example will be composed of two separate agents - a publisher called
310+`/app/todo.hoon` and a subscriber called `/app/todo-watcher.hoon`, which will
311+live on separate ships. It will be a very rudimentary To-Do app - to-do tasks
312+will be poked into the publisher and sent out to the subscriber as `%fact`s,
313+which will just print them to the dojo. It will have its types defined in
314+`/sur/todo.hoon`, and it will have a couple of `mark` files for pokes and
315+updates: `/mar/todo/action.hoon` and `/mar/todo/update.hoon`.
316+
317+Before we get into trying it out, we'll first walk through the `/sur` file, mark
318+files, and each agent.
319+
320+### Types and marks
321+
322+#### `/sur/todo.hoon`
323+
324+```hoon
325+|%
326++$ id @
327++$ name @t
328++$ task [=name done=?]
329++$ tasks (map id task)
330++$ who @p
331++$ friends (set who)
332++$ action
333+ $% [%add =name]
334+ [%del =id]
335+ [%toggle =id]
336+ [%rename =id =name]
337+ [%allow =who]
338+ [%kick =who]
339+ ==
340++$ update
341+ $% [%add =id =name]
342+ [%del =id]
343+ [%toggle =id]
344+ [%rename =id =name]
345+ [%initial =tasks]
346+ ==
347+--
348+```
349+
350+This file defines most of the types for the agents. The list of to-do tasks will
351+be stored in the state of the publisher agent as the `tasks` type, a `(map id task)`, where a `task` is a `[=name done=?]`. The set of ships allowed to
352+subscribe will be stored in `friends`, a `(set @p)`, also in the publisher's
353+state. After that, there are the head-tagged unions of accepted poke `action`s
354+and `update`s for subscribers.
355+
356+#### `/mar/todo/action.hoon`
357+
358+```hoon
359+/- todo
360+|_ =action:todo
361+++ grab
362+ |%
363+ ++ noun action:todo
364+ --
365+++ grow
366+ |%
367+ ++ noun action
368+ --
369+++ grad %noun
370+--
371+```
372+
373+This is a very simple mark file for the `action` type.
374+
375+#### `/mar/todo/update.hoon`
376+
377+```hoon
378+/- todo
379+|_ =update:todo
380+++ grab
381+ |%
382+ ++ noun update:todo
383+ --
384+++ grow
385+ |%
386+ ++ noun update
387+ --
388+++ grad %noun
389+--
390+```
391+
392+This is a very simple mark file for the `update` type.
393+
394+### Publisher
395+
396+#### `/app/todo.hoon`
397+
398+```hoon
399+/- todo
400+/+ default-agent, dbug
401+|%
402++$ versioned-state
403+ $% state-0
404+ ==
405++$ state-0 [%0 =friends:todo =tasks:todo]
406++$ card card:agent:gall
407+--
408+%- agent:dbug
409+=| state-0
410+=* state -
411+^- agent:gall
412+|_ =bowl:gall
413++* this .
414+ def ~(. (default-agent this %.n) bowl)
415+++ on-init
416+ ^- (quip card _this)
417+ `this
418+++ on-save
419+ ^- vase
420+ !>(state)
421+++ on-load
422+ |= old-state=vase
423+ ^- (quip card _this)
424+ =/ old !<(versioned-state old-state)
425+ ?- -.old
426+ %0 `this(state old)
427+ ==
428+++ on-poke
429+ |= [=mark =vase]
430+ |^ ^- (quip card _this)
431+ ?> =(src.bowl our.bowl)
432+ ?+ mark (on-poke:def mark vase)
433+ %todo-action
434+ =^ cards state
435+ (handle-poke !<(action:todo vase))
436+ [cards this]
437+ ==
438+ ++ handle-poke
439+ |= =action:todo
440+ ^- (quip card _state)
441+ ?- -.action
442+ %add
443+ :_ state(tasks (~(put by tasks) now.bowl [name.action %.n]))
444+ :~ [%give %fact ~[/updates] %todo-update !>(`update:todo`[%add now.bowl name.action])]
445+ ==
446+ ::
447+ %del
448+ :_ state(tasks (~(del by tasks) id.action))
449+ :~ [%give %fact ~[/updates] %todo-update !>(`update:todo`action)]
450+ ==
451+ ::
452+ %toggle
453+ :_ state(tasks (~(jab by tasks) id.action |=(=task:todo task(done !done.task))))
454+ :~ [%give %fact ~[/updates] %todo-update !>(`update:todo`action)]
455+ ==
456+ ::
457+ %rename
458+ :_ state(tasks (~(jab by tasks) id.action |=(=task:todo task(name name.action))))
459+ :~ [%give %fact ~[/updates] %todo-update !>(`update:todo`action)]
460+ ==
461+ ::
462+ %allow
463+ `state(friends (~(put in friends) who.action))
464+ ::
465+ %kick
466+ :_ state(friends (~(del in friends) who.action))
467+ :~ [%give %kick ~[/updates] `who.action]
468+ ==
469+ ==
470+ --
471+++ on-watch
472+ |= =path
473+ ^- (quip card _this)
474+ ?+ path (on-watch:def path)
475+ [%updates ~]
476+ ?> (~(has in friends) src.bowl)
477+ :_ this
478+ :~ [%give %fact ~ %todo-update !>(`update:todo`initial+tasks)]
479+ ==
480+ ==
481+++ on-leave on-leave:def
482+++ on-peek on-peek:def
483+++ on-agent on-agent:def
484+++ on-arvo on-arvo:def
485+++ on-fail on-fail:def
486+--
487+```
488+
489+This is the publisher agent, `todo.hoon`. The bulk of its logic is in its
490+`on-poke` arm, where it handles the various possible actions like `%add`ing a
491+task, `%toggle`ing its "done" state, `%rename`ing a task, and so on. It also has
492+a couple of `action`s for `%allow`ing and `%kick`ing subscribers.
493+
494+Most of these cases both update the state of the agent, as well as producing
495+`%fact` cards to send out to subscribers with the new data.
496+
497+You'll notice it only allows these pokes from the local ship, and enforces this
498+in `on-poke` with:
499+
500+```hoon
501+?> =(src.bowl our.bowl)
502+```
503+
504+Let's look at `on-watch`:
505+
506+```hoon
507+++ on-watch
508+ |= =path
509+ ^- (quip card _this)
510+ ?+ path (on-watch:def path)
511+ [%updates ~]
512+ ?> (~(has in friends) src.bowl)
513+ :_ this
514+ :~ [%give %fact ~ %todo-update !>(`update:todo`initial+tasks)]
515+ ==
516+ ==
517+```
518+
519+When `on-watch` gets a subscription request, it checks whether the requesting
520+ship is in the `friends` set, and crashes if it is not. If they're in `friends`,
521+it produces a `%fact` card with a null `(list path)`, which means it goes only
522+to the new subscriber. This `%fact` contains the entire `tasks` map as it
523+currently exists, getting the new subscriber up to date.
524+
525+### Subscriber
526+
527+```hoon
528+/- todo
529+/+ default-agent, dbug
530+|%
531++$ versioned-state
532+ $% state-0
533+ ==
534++$ state-0 [%0 ~]
535++$ card card:agent:gall
536+--
537+%- agent:dbug
538+=| state-0
539+=* state -
540+^- agent:gall
541+|_ =bowl:gall
542++* this .
543+ def ~(. (default-agent this %.n) bowl)
544+++ on-init
545+ ^- (quip card _this)
546+ `this
547+++ on-save
548+ ^- vase
549+ !>(state)
550+++ on-load
551+ |= old-state=vase
552+ ^- (quip card _this)
553+ =/ old !<(versioned-state old-state)
554+ ?- -.old
555+ %0 `this(state old)
556+ ==
557+++ on-poke
558+ |= [=mark =vase]
559+ ^- (quip card _this)
560+ ?> =(src.bowl our.bowl)
561+ ?+ mark (on-poke:def mark vase)
562+ %noun
563+ =/ action !<(?([%sub @p] [%unsub @p]) vase)
564+ ?- -.action
565+ %sub
566+ :_ this
567+ :~ [%pass /todos %agent [+.action %todo] %watch /updates]
568+ ==
569+ %unsub
570+ :_ this
571+ :~ [%pass /todos %agent [+.action %todo] %leave ~]
572+ ==
573+ ==
574+ ==
575+++ on-watch on-watch:def
576+++ on-leave on-leave:def
577+++ on-peek on-peek:def
578+++ on-agent
579+ |= [=wire =sign:agent:gall]
580+ ^- (quip card _this)
581+ ?+ wire (on-agent:def wire sign)
582+ [%todos ~]
583+ ?+ -.sign (on-agent:def wire sign)
584+ %watch-ack
585+ ?~ p.sign
586+ ((slog '%todo-watcher: Subscribe succeeded!' ~) `this)
587+ ((slog '%todo-watcher: Subscribe failed!' ~) `this)
588+ ::
589+ %kick
590+ %- (slog '%todo-watcher: Got kick, resubscribing...' ~)
591+ :_ this
592+ :~ [%pass /todos %agent [src.bowl %todo] %watch /updates]
593+ ==
594+ ::
595+ %fact
596+ ?+ p.cage.sign (on-agent:def wire sign)
597+ %todo-update
598+ ~& !<(update:todo q.cage.sign)
599+ `this
600+ ==
601+ ==
602+ ==
603+++ on-arvo on-arvo:def
604+++ on-fail on-fail:def
605+--
606+```
607+
608+This is the subscriber agent. Since it's just for demonstrative purposes, it has
609+no state and just prints updates it receives. In practice it would probably keep the `tasks` map it receives in its own state, and then update it as it receives new
610+`%fact`s.
611+
612+The `on-poke` arm is fairly simple - it accepts two pokes, to either `[%sub ~some-ship]` or `[%unsub ~some-ship]`.
613+
614+The `on-agent` arm will print whether a subscription request succeeded or
615+failed, as well as printing a message when it gets kicked. When it receives a
616+`%fact` from the publisher agent, it will just print it to the terminal with a
617+`~&` expression.
618+
619+### Trying it out
620+
621+We're going to try this between two different ships. The first ship will be the usual fakezod. We'll add both `mark` files, the `/sur` file, and the `todo.hoon` agent to the `%base` desk of our fakezod, putting them in the following directories:
622+
623+```
624+base
625+├── app
626+│ └── todo.hoon
627+├── mar
628+│ └── todo
629+│ ├── action.hoon
630+│ └── update.hoon
631+└── sur
632+ └── todo.hoon
633+```
634+
635+In `~zod`'s dojo, we can `|commit %base`, and then start the `%todo` agent:
636+
637+```
638+|rein %base [& %todo]
639+```
640+
641+Now we need to spin up another fake ship. We'll use `~nut` in this example:
642+
643+```
644+urbit -F nut
645+```
646+
647+Once it's booted, we can `|mount %base` and then add just the `update.hoon` mark file, the `/sur` file, and the `todo-watcher.hoon` agent like so:
648+
649+```
650+base
651+├── app
652+│ └── todo-watcher.hoon
653+├── mar
654+│ └── todo
655+│ └── update.hoon
656+└── sur
657+ └── todo.hoon
658+```
659+
660+On `~nut` we can then `|commit %base`, and start the `%todo-watcher` agent:
661+
662+```
663+|rein %base [& %todo-watcher]
664+```
665+
666+Now, on `~nut`, let's try subscribing:
667+
668+```
669+> :todo-watcher [%sub ~zod]
670+>=
671+%todo-watcher: Subscribe failed!
672+```
673+
674+Our `%todo-watcher` agent tried, but received a negative `%watch-ack` from
675+`%todo`, because we haven't yet added `~nut` to the `friends` set of allowed
676+ships. Let's now remedy that on `~zod`:
677+
678+```
679+> :todo &todo-action [%allow ~nut]
680+>=
681+```
682+
683+Let's also add a couple of to-do tasks, on `~zod`:
684+
685+```
686+> :todo &todo-action [%add 'foo']
687+>=
688+> :todo &todo-action [%add 'bar']
689+>=
690+```
691+
692+If we now check its state with `+dbug`, we'll see they're in the `tasks` map,
693+and `~nut` will also now be in the `friends` set:
694+
695+```
696+> [ %0
697+ friends={~nut}
698+ tasks
699+ { [ p=170.141.184.505.349.079.206.522.766.950.035.095.552
700+ q=[name='foo' done=%.n]
701+ ]
702+ [ p=170.141.184.505.349.079.278.538.984.166.386.565.120
703+ q=[name='bar' done=%.n]
704+ ]
705+ }
706+]
707+> :todo +dbug
708+>=
709+```
710+
711+Let's now try subscribing again on `~nut`:
712+
713+```
714+> :todo-watcher [%sub ~zod]
715+>=
716+%todo-watcher: Subscribe succeeded!
717+[ %initial
718+ tasks
719+ { [ p=170.141.184.505.349.079.206.522.766.950.035.095.552
720+ q=[name='foo' done=%.n]
721+ ]
722+ [ p=170.141.184.505.349.079.278.538.984.166.386.565.120
723+ q=[name='bar' done=%.n]
724+ ]
725+ }
726+]
727+```
728+
729+As you can see, this time it's worked, and we've immediately received the
730+initial `tasks` map.
731+
732+Now, let's try adding another task on `~zod`:
733+
734+```
735+> :todo &todo-action [%add 'baz']
736+>=
737+```
738+
739+On `~nut`, we'll see it has received the `%fact` with the new task in it:
740+
741+```
742+[ %add
743+ id=170.141.184.505.349.082.779.030.192.959.445.270.528
744+ name='baz'
745+]
746+```
747+
748+Let's try toggle its done state on `~zod`:
749+
750+```
751+> :todo &todo-action [%toggle 170.141.184.505.349.082.779.030.192.959.445.270.528]
752+>=
753+```
754+
755+`~nut` will again get the `%fact`:
756+
757+```
758+[ %toggle
759+ id=170.141.184.505.349.082.779.030.192.959.445.270.528
760+]
761+```
762+
763+Recall that incoming subscriptions are stored in `sup.bowl`, and outgoing
764+subscriptions are stored in `wex.bowl`. Let's have a look at the incoming
765+subscription on `~zod`:
766+
767+```
768+> [ path=/updates
769+ from=~nut
770+ duct=~[/gall/sys/req/~nut/todo /ames/bone/~nut/1 //ames]
771+]
772+> :todo +dbug [%incoming %ship ~nut]
773+>=
774+```
775+
776+On `~nut`, let's look at the outgoing subscription:
777+
778+```
779+> [wire=/todos agnt=[~zod %todo] path=/updates ackd=%.y]
780+> :todo-watcher +dbug [%outgoing %ship ~zod]
781+>=
782+```
783+
784+Now on `~zod`, let's try kicking `~nut` and removing it from our `friends` set:
785+
786+```
787+> :todo &todo-action [%kick ~nut]
788+>=
789+```
790+
791+On `~nut`, we'll see it got the `%kick`, tried resubscribing automatically, but
792+was rejected because `~nut` is no longer in `friends`:
793+
794+```
795+%todo-watcher: Got kick, resubscribing...
796+%todo-watcher: Subscribe failed!
797+```
798+
799+## Summary
800+
801+- Incoming subscription requests arrive in an agent's `on-watch` arm.
802+- An agent will define various subscription `path`s in its `on-watch` arm, which
803+ others can subscribe to.
804+- Gall will automatically produce a negative `%watch-ack` if `on-watch` crashed,
805+ and a positive one if it was successful.
806+- Incoming subscribers are recorded in the `sup` field of the `bowl`.
807+- `on-watch` can produce a `%fact` with a null `(list path)` which will go only
808+ to the new subscriber.
809+- Updates are sent to subscribers in `%fact` cards, and contain a `cage` with a
810+ `mark` and some data in a `vase`.
811+- `%fact`s are sent to all subscribers of the paths specified in the `(list path)`.
812+- A subscriber can be kicked from subscription paths with a `%kick` card
813+ specifying the ship in the `(unit ship)`. All subscribers of the specified
814+ paths will be kicked if the `(unit ship)` is null.
815+- An outgoing subscription can be initiated with a `%watch` card.
816+- The `%watch-ack` will come back in to the subscriber's `on-agent` arm as a
817+ `sign`, and may be positive or negative, depending on whether the `(unit tang)` is null.
818+- `%kick`s will also arrive in the subscriber's `on-agent` arm as a `sign`.
819+ Since kicks may not be intentional, the subscriber should attempt to
820+ resubscribe and only give up if the subsequent `%watch-ack` is negative.
821+- `%fact`s will also arrive in the subscriber's `on-agent` arm.
822+- All such `sign`s that arrive in `on-agent` will also have a `wire`.
823+- The `wire` for subscription updates to arrive on is specified in the initial
824+ `%watch` card.
825+- A subscriber can unsubscribe by passing a `%leave` card on the original
826+ `wire`.
827+
828+## Exercises
829+
830+- Have a look at the [Strings Guide](/docs/hoon/guides/strings) if you're
831+ already familiar with decoding/encoding atoms in strings.
832+- Try running through the [Example](#example) yourself, if you've not done so already.
833+- Try modifying `%todo-watcher` to recording the data it receives in its state,
834+ rather than simply printing it to the terminal.
content/docs/userspace/gall-guide/9-vanes.mdnew file+281
@@ -0,0 +1,281 @@
1++++
2+title = "9. Vanes"
3+weight = 45
4+template = "doc.html"
5++++
6+
7+In this lesson we're going to look at interacting with vanes (kernel modules).
8+The API for each vane consists of `task`s it can take, and `gift`s it can
9+return. The `task`s and `gift`s for each vane are defined in its section of
10+`lull.hoon`. Here's the `task:iris`s and `gift:iris`s for Iris, the HTTP client
11+vane, as an example:
12+
13+```hoon
14+|%
15++$ gift
16+ $% [%request id=@ud request=request:http]
17+ [%cancel-request id=@ud]
18+ [%http-response =client-response]
19+ ==
20++$ task
21+ $~ [%vega ~]
22+ $% $>(%born vane-task)
23+ $>(%trim vane-task)
24+ $>(%vega vane-task)
25+ [%request =request:http =outbound-config]
26+ [%cancel-request ~]
27+ [%receive id=@ud =http-event:http]
28+ ==
29+```
30+
31+The API of each vane is documented in its respective section of the [Arvo
32+documentation](/docs/arvo/overview). Each vane has a detailed API reference and
33+examples of their usage. There are far too many `task`s and `gift`s across the
34+vanes to cover here, so in the [`Example`](#example) section of this document,
35+we'll just look at a single, simple example with a Behn timer. The basic pattern
36+in the example is broadly applicable to the other vanes as well.
37+
38+## Sending a vane task
39+
40+A `task` can be sent to a vane by `%pass`ing it an `%arvo` card. We touched on
41+these in the [Cards](/docs/userspace/gall-guide/5-cards) lesson, but we'll
42+briefly recap it here. The type of the card is as follows:
43+
44+```hoon
45+[%pass path %arvo note-arvo]
46+```
47+
48+The `path` will just be the `wire` you want the response to arrive on. The `note-arvo` is the following union:
49+
50+```hoon
51++$ note-arvo
52+ $~ [%b %wake ~]
53+ $% [%a task:ames]
54+ [%b task:behn]
55+ [%c task:clay]
56+ [%d task:dill]
57+ [%e task:eyre]
58+ [%g task:gall]
59+ [%i task:iris]
60+ [%j task:jael]
61+ [%$ %whiz ~]
62+ [@tas %meta vase]
63+ ==
64+```
65+
66+The letter tags just specify which vane it goes to, and then follows the `task`
67+itself. Here are a couple of examples. The first sends a `%wait` `task:behn` to
68+Behn, setting a timer to go off one minute in the future. The second sends a
69+`%warp` `task:clay` to Clay, asking whether `sys.kelvin` exists on the `%base`
70+desk.
71+
72+```hoon
73+[%pass /some/wire %arvo %b %wait (add ~m1 now.bowl)]
74+[%pass /some/wire %arvo %c %warp our.bowl %base ~ %sing %u da+now.bowl /sys/kelvin]
75+```
76+
77+## Receiving a vane gift
78+
79+Once a `task` has been sent to a vane, any `gift`s the vane sends back in
80+response will arrive in the `on-arvo` arm of your agent core. The `on-arvo` arm
81+exclusively handles such vane `gift`s. The `gift`s will arrive in a `sign-arvo`,
82+along with the `wire` specified in the original request. The `on-arvo` arm
83+produces a `(quip card _this)` like usual, so it would look like:
84+
85+```hoon
86+++ on-arvo
87+ |= [=wire =sign-arvo]
88+ ^- (quip card _this)
89+ .....
90+```
91+
92+A `sign-arvo` is the following structure:
93+
94+```hoon
95++$ sign-arvo
96+ $% [%ames gift:ames]
97+ $: %behn
98+ $% gift:behn
99+ $>(%wris gift:clay)
100+ $>(%writ gift:clay)
101+ $>(%mere gift:clay)
102+ $>(%unto gift:gall)
103+ ==
104+ ==
105+ [%clay gift:clay]
106+ [%dill gift:dill]
107+ [%eyre gift:eyre]
108+ [%gall gift:gall]
109+ [%iris gift:iris]
110+ [%jael gift:jael]
111+ ==
112+```
113+
114+The head of the `sign-arvo` will be the name of the vane like `%behn`, `%clay`,
115+etc. The tail will be the `gift` itself. Here are a couple of `sign-arvo`
116+examples, and the responses to the example `task`s in the previous section:
117+
118+```hoon
119+[%behn %wake ~]
120+```
121+
122+```
123+[ %clay
124+ [ %writ
125+ p
126+ [ ~
127+ [ p=[p=%u q=[%da p=~2021.11.17..13.55.00..c195] r=%base]
128+ q=/sys/kelvin
129+ r=[p=%flag q=[#t/?(%.y %.n) q=0]]
130+ ]
131+ ]
132+ ]
133+]
134+```
135+
136+The typical pattern is to first test the `wire` with something like a wutlus
137+(`?+`) expression, and then test the `sign-arvo`. Since most `gift`s are
138+head-tagged, you can test both the vane and the gift at the same time like:
139+
140+```hoon
141+?+ sign-arvo (on-arvo:def wire sign-arvo)
142+ [%behn %wake *]
143+ .....
144+....
145+```
146+
147+## Example
148+
149+Here's a very simple example that takes a poke of a `@dr` (a relative date-time
150+value) and sends Behn a `%wait` `task:behn`, setting a timer to go off `@dr` in
151+the future. When the timer goes off, `on-arvo` will take the `%wake` `gift:behn`
152+and print "Ding!" to the terminal.
153+
154+#### `ding.hoon`
155+
156+```hoon
157+/+ default-agent, dbug
158+|%
159++$ card card:agent:gall
160+--
161+%- agent:dbug
162+^- agent:gall
163+|_ =bowl:gall
164++* this .
165+ def ~(. (default-agent this %.n) bowl)
166+++ on-init on-init:def
167+++ on-save on-save:def
168+++ on-load on-load:def
169+++ on-poke
170+ |= [=mark =vase]
171+ ^- (quip card _this)
172+ ?+ mark (on-poke:def mark vase)
173+ %noun
174+ :_ this
175+ :~ [%pass /timers %arvo %b %wait (add now.bowl !<(@dr vase))]
176+ ==
177+ ==
178+++ on-watch on-watch:def
179+++ on-leave on-leave:def
180+++ on-peek on-peek:def
181+++ on-agent on-agent:def
182+++ on-arvo
183+ |= [=wire =sign-arvo]
184+ ^- (quip card _this)
185+ ?+ wire (on-arvo:def wire sign-arvo)
186+ [%timers ~]
187+ ?+ sign-arvo (on-arvo:def wire sign-arvo)
188+ [%behn %wake *]
189+ ?~ error.sign-arvo
190+ ((slog 'Ding!' ~) `this)
191+ (on-arvo:def wire sign-arvo)
192+ ==
193+ ==
194+++ on-fail on-fail:def
195+--
196+```
197+
198+Let's examine the `on-poke` arm:
199+
200+```hoon
201+++ on-poke
202+ |= [=mark =vase]
203+ ^- (quip card _this)
204+ ?+ mark (on-poke:def mark vase)
205+ %noun
206+ :_ this
207+ :~ [%pass /timers %arvo %b %wait (add now.bowl !<(@dr vase))]
208+ ==
209+ ==
210+```
211+
212+A Behn `%wait` task has the format `[%wait @da]` - the `@da` (an absolute
213+date-time value) is the time the timer should go off. The `vase` of the poke
214+takes a `@dr`, so we extract it directly into an `add` expression, producing a
215+date-time `@dr` from now. Behn will receive the `%wait` task and set the timer
216+in Unix. When it fires, Behn will produce a `%wake` `gift:behn` and deliver it
217+to `on-arvo`, on the `wire` we specified (`/timers`). Here's the `on-arvo` arm:
218+
219+```hoon
220+++ on-arvo
221+ |= [=wire =sign-arvo]
222+ ^- (quip card _this)
223+ ?+ wire (on-arvo:def wire sign-arvo)
224+ [%timers ~]
225+ ?+ sign-arvo (on-arvo:def wire sign-arvo)
226+ [%behn %wake *]
227+ ?~ error.sign-arvo
228+ ((slog 'Ding!' ~) `this)
229+ (on-arvo:def wire sign-arvo)
230+ ==
231+ ==
232+```
233+
234+First we check the `wire` is `/timers`, and then we check the `sign-arvo` begins
235+with `[%behn %wake ....]`. Behn's `%wake` gift has the following format:
236+
237+```hoon
238+[%wake error=(unit tang)]
239+```
240+
241+The `error` is null if the timer fired successfully, and contains an error in
242+the `tang` if it did not. We therefore test whether `error.sign-arvo` is `~`,
243+and if it is, we print `Ding!` to the terminal. If the `wire`, `sign-arvo` or
244+`error` are something unexpected, we pass it to `%default-agent`, which
245+will just crash and print an error message.
246+
247+Let's try it out. Save the agent above as `/app/ding.hoon` on the `%base` desk
248+and `|commit %base`. Then, start the agent with `|rein %base [& %ding]`.
249+
250+Next, in the dojo let's try poking our agent, setting a timer for five seconds
251+from now:
252+
253+```
254+> :ding ~s5
255+>=
256+```
257+
258+After approximately five seconds, we see the timer fired successfully:
259+
260+```
261+> Ding!
262+```
263+
264+## Summary
265+
266+- Each vane has an API composed of `task`s it takes and `gift`s it produces.
267+- Each vane's `task`s and `gift`s are defined in `lull.hoon`
268+- Each vane's section of the [Arvo documentation](/docs/arvo/overview) include
269+ an API reference that explains its `task`s and `gift`s, as well as an Examples
270+ section demonstrating their usage.
271+- Vane `task`s can be sent to vanes by `%pass`ing them an `%arvo` `card`.
272+- Vane `gift`s come back to the `on-arvo` arm of the agent core in a
273+ `sign-arvo`.
274+
275+## Exercises
276+
277+- Run through the [Example](#example) yourself if you've not done so already.
278+- Have a look at some vane sections of `lull.hoon` to familiarize yourself with
279+ its structure.
280+- Have a quick look at the API reference sections of a couple of vanes in the
281+ [Arvo documentation](/docs/arvo/overview).
content/docs/userspace/gall-guide/_index.mdnew file+45
@@ -0,0 +1,45 @@
1++++
2+title = "Gall Guide"
3+weight = 5
4+sort_by = "weight"
5+template = "sections/docs/chapters.html"
6+insert_anchor_links = "right"
7++++
8+
9+## Table of Contents
10+
11+- [Introduction](/docs/userspace/gall-guide/intro)
12+
13+#### Lessons
14+
15+1. [Prologue](/docs/userspage/gall-guide/1-arvo) - This lesson provides an
16+ overview of the Arvo operating system, and some other useful background
17+ information.
18+2. [The Agent Core](/docs/userspace/gall-guide/2-agent) - This lesson goes over
19+ the basic structure of a Gall agent.
20+3. [Imports and Aliases](/docs/userspace/gall-guide/3-imports-and-aliases) -
21+ This lesson covers some useful libraries, concepts and boilerplate commonly
22+ used when writing Gall agents.
23+4. [Lifecycle](/docs/userspace/gall-guide/4-lifecycle) - This lesson introduces
24+ the state management arms of an agent.
25+5. [Cards](/docs/userspace/gall-guide/5-cards) - This lesson covers `card`s -
26+ the structure used to pass messages to other agents and vanes.
27+6. [Pokes](/docs/userspace/gall-guide/6-pokes) - This lesson covers sending and
28+ receiving one-off messages called "pokes" between agents.
29+7. [Structures and Marks](/docs/userspace/gall-guide/7-sur-and-marks) - This
30+ lesson talks about importing type defintions, and writing `mark` files.
31+8. [Subscriptions](/docs/userspace/gall-guide/8-subscriptions) - This lesson
32+ goes through the mechanics of subscriptions - both inbound and outbound.
33+9. [Vanes](/docs/userspace/gall-guide/9-vanes) - This lesson explains how to
34+ interact with vanes (kernel modules) from an agent.
35+10. [Scries](/docs/userspace/gall-guide/10-scry) - This lesson gives an overview
36+ of scrying Gall agents, and how scry endpoints are defined in agents.
37+11. [Failure](/docs/userspace/gall-guide/11-fail) - This lesson covers how Gall
38+ handles certain errors and crashes, as well as the concept of a helper core.
39+12. [Next Steps](/docs/userspace/gall-guide/12-next-steps) - The Gall Guide is
40+ now complete - here are some things you can look at next.
41+
42+#### Appendix
43+
44+- [Types](/docs/userspace/gall-guide/types) - A reference for a few of
45+ the types used in the Gall Guide.
content/docs/userspace/gall-guide/intro.mdnew file+83
@@ -0,0 +1,83 @@
1++++
2+title = "Introduction"
3+weight = 1
4+template = "doc.html"
5++++
6+
7+This guide will walk through everything you need to know to write your own Gall
8+agents.
9+
10+The Gall Guide is suitable for anyone with an intermediate knowledge of Hoon. If
11+you've worked through [Hoon School](/docs/hoon/hoon-school/intro) or something
12+equivalent, you should be fine.
13+
14+## What are Gall agents?
15+
16+Gall is one of the eight vanes (kernel modules) of Arvo, Urbit's operating
17+system. Gall's purpose is to manage userspace applications called _agents_.
18+
19+An agent is a piece of software that is primarily focused on maintaining and
20+distributing a piece of state with a defined structure. It exposes an interface
21+that lets programs read, subscribe to, and manipulate the state. Every event
22+happens in an atomic transaction, so the state is never inconsistent. Since the
23+state is permanent, when the agent is upgraded with a change to the structure of
24+the state, the developer provides a migration function from the old state type
25+to the new state type.
26+
27+It's not too far off to think of an agent as simply a database with
28+developer-defined logic. But an agent is significantly less constrained than a
29+database. Databases are usually tightly constrained in one or more ways because
30+they need to provide certain guarantees (like atomicity) or optimizations (like
31+indexes). Urbit is a single-level store, so atomicity comes for free. Many
32+applications don't use databases because they need relational indices; rather,
33+they use them for their guarantees around persistence. Some do need the indices,
34+though, and it's not hard to imagine an agent which provides a SQL-like
35+interface.
36+
37+On the other hand, an agent is also a lot like what many systems call a
38+"service". An agent is permanent and addressable -- a running program can talk
39+to an agent just by naming it. An agent can perform IO, unlike most databases.
40+This is a critical part of an agent: it performs IO along the same transaction
41+boundaries as changes to its state, so if an effect happens, you know that the
42+associated state change has happened.
43+
44+But the best way to think about an agent is as a state machine. Like a state
45+machine, any input could happen at any time, and it must react coherently to
46+that input. Output (effects) and the next state of the machine are both pure
47+functions of the previous state and the input event.
48+
49+## Table of Contents
50+
51+#### Lessons
52+
53+1. [Prologue](/docs/userspage/gall-guide/1-arvo) - This lesson provides an
54+ overview of the Arvo operating system, and some other useful background
55+ information.
56+2. [The Agent Core](/docs/userspace/gall-guide/2-agent) - This lesson goes over
57+ the basic structure of a Gall agent.
58+3. [Imports and Aliases](/docs/userspace/gall-guide/3-imports-and-aliases) -
59+ This lesson covers some useful libraries, concepts and boilerplate commonly
60+ used when writing Gall agents.
61+4. [Lifecycle](/docs/userspace/gall-guide/4-lifecycle) - This lesson introduces
62+ the state management arms of an agent.
63+5. [Cards](/docs/userspace/gall-guide/5-cards) - This lesson covers `card`s -
64+ the structure used to pass messages to other agents and vanes.
65+6. [Pokes](/docs/userspace/gall-guide/6-pokes) - This lesson covers sending and
66+ receiving one-off messages called "pokes" between agents.
67+7. [Structures and Marks](/docs/userspace/gall-guide/7-sur-and-marks) - This
68+ lesson talks about importing type defintions, and writing `mark` files.
69+8. [Subscriptions](/docs/userspace/gall-guide/8-subscriptions) - This lesson
70+ goes through the mechanics of subscriptions - both inbound and outbound.
71+9. [Vanes](/docs/userspace/gall-guide/9-vanes) - This lesson explains how to
72+ interact with vanes (kernel modules) from an agent.
73+10. [Scries](/docs/userspace/gall-guide/10-scry) - This lesson gives an overview
74+ of scrying Gall agents, and how scry endpoints are defined in agents.
75+11. [Failure](/docs/userspace/gall-guide/11-fail) - This lesson covers how Gall
76+ handles certain errors and crashes, as well as the concept of a helper core.
77+12. [Next Steps](/docs/userspace/gall-guide/12-next-steps) - The Gall Guide is
78+ now complete - here are some things you can look at next.
79+
80+#### Appendix
81+
82+- [Types](/docs/userspace/gall-guide/types) - A reference for a few of
83+ the types used in the Gall Guide.
content/docs/userspace/gall-guide/types.mdnew file+217
@@ -0,0 +1,217 @@
1++++
2+title = "Appendix: Types"
3+weight = 60
4+template = "doc.html"
5++++
6+
7+This document explains a few of the types commonly used in Gall agents. In
8+addition to these, the [Data Types](/docs/arvo/gall/data-types) section of the
9+Gall vane documentation is a useful reference. In particular, the
10+[`bitt`](/docs/arvo/gall/data-types#bitt),
11+[`boat`](/docs/arvo/gall/data-types#boat) and
12+[`bowl`](/docs/arvo/gall/data-types#bowl) entries, as well as the whole
13+[`agent`](/docs/arvo/gall/data-types#agent) subsection.
14+
15+## `vase`
16+
17+Urbit needs to be able to send typed data between vanes and agents, as well as
18+over the network to other ships. While cell structures can easily be validated,
19+atom auras cannot. To solve this problem, Urbit wraps such data in a vase before
20+sending it. Vases are used extensively - almost all data your agent will send
21+and received is wrapped in a vase.
22+
23+A vase is just a cell with data in the tail and the type of the data in the
24+head. Its formal definition is:
25+
26+```hoon
27++$ vase [p=type q=*]
28+```
29+
30+Here's what it looks like if we bunt a vase in the dojo:
31+
32+```
33+> *vase
34+[#t/* q=0]
35+```
36+
37+There are two simple runes used to create and unpack vases. We'll look at each
38+of these next.
39+
40+### Create a `vase`
41+
42+The [zapgar](https://urbit.org/docs/hoon/reference/rune/zap#-zapgar) rune (`!>`)
43+takes a single argument of any noun, and wraps it in a vase. For example, in the
44+dojo:
45+
46+```
47+> !>([1 2 3])
48+[#t/[@ud @ud @ud] q=[1 2 3]]
49+
50+> !>('foo')
51+[#t/@t q=7.303.014]
52+
53+> !>([[0xdead 0xb33f] 'foo'])
54+[#t/[[@ux @ux] @t] q=[[57.005 45.887] 7.303.014]]
55+
56+> !>(foo='bar')
57+[#t/foo=@t q=7.496.034]
58+```
59+
60+You would typically use `!>` as part of a [`cage`](#cage) when you're
61+constructing a `card` like a poke or a `%fact` gift to be sent off.
62+
63+### Extract data from `vase`
64+
65+The [zapgal](https://urbit.org/docs/hoon/reference/rune/zap#-zapgal) rune (`!<`)
66+takes two arguments: A mold specifying the type to try and extract the data as,
67+and the vase to be extracted.
68+
69+Let's look at an example in the dojo. First, let's create a vase of `[@t @ux @ud]`:
70+
71+```
72+> =myvase !>(['foo' 0xabcd 123])
73+> myvase
74+[#t/[@t @ux @ud] q=[7.303.014 43.981 123]]
75+```
76+
77+Next, let's try extracting our vase:
78+
79+```
80+> !< [@t @ux @ud] myvase
81+['foo' 0xabcd 123]
82+```
83+
84+Now let's try asking for a `@p` rather than `@t`:
85+
86+```
87+> !< [@p @ux @ud] myvase
88+-need.@p
89+-have.@t
90+nest-fail
91+```
92+
93+As you can see, it will crash if the type does not exactly match. Note that
94+rather than using `!<`, you can also just clam the tail of the vase like:
95+
96+```
97+> ((trel @t @ux @ud) +.myvase)
98+[p='foo' q=0xabcd r=123]
99+```
100+
101+The only problem is that you can't tell if the auras were wrong:
102+
103+```
104+> ((trel @p @ud @ux) +.myvase)
105+[p=~sibtel-tallyd q=43.981 r=0x7b]
106+```
107+
108+You'd typically use `!<` on the data in `card`s that come in from other ships,
109+agents, etc.
110+
111+## `mark`
112+
113+The `mark` type is just a `@tas` like `%foo`, and specifies the Clay filetype of
114+some data. The `mark` corresponds to a mark file in the `/mar` directory, so a
115+`mark` of `%foo` corresponds to `/mar/foo/hoon`. Mark files are used for saving
116+data in Clay, validating data sent between agents or over the network, and
117+converting between different data types. For more information about mark files,
118+you can refer to the [Marks section of the Clay
119+documentation](/docs/arvo/clay/marks/marks).
120+
121+## `cage`
122+
123+A `cage` is a cell of a [`mark`](#mark) and a [`vase`](#vase), like `[%foo !>('bar')]`. The data in the vase should match the data type of the specified
124+mark.
125+
126+Most data sent between agents, either locally or over the network, will be in a
127+cage. When data comes in, Gall will validate the data in the vase with the given
128+mark. Additionally, the data may be converted to a different mark if appropriate
129+conversion routines exist in the mark file. This is most commonly done when
130+talking to a web front-end via Eyre's channel system - outgoing data will be
131+automatically converted to a `%json` mark and incoming data will be converted
132+from `%json` to the mark your agent expects.
133+
134+## `quip`
135+
136+`(quip a b)` is equivalent to `[(list a) b]`, it's just a more convenient way to
137+specify it. Most arms of an agent return a `(quip card _this)`, which is a list
138+of effects and a new state.
139+
140+## `path`
141+
142+The `path` type is formally defined as:
143+
144+```hoon
145++$ path (list knot)
146+```
147+
148+A knot is a `@ta` text atom (see the [Strings guide](/docs/hoon/guides/strings)
149+for details), so a `path` is just a list of text. Rather than having to write
150+`[~.foo ~.bar ~.baz ~]` though, it has its own syntax which looks like
151+`/foo/bar/baz`.
152+
153+A `path` is just a general type used for several different purposes throughout
154+Arvo. Its elements have no inherent significance, it depends on the context. In
155+a Gall agent, a `path` is most commonly a subscription path - you might
156+subscribe for updates to `/foo/bar` on another agent, or another agent might
157+subscribe to `/baz` on your agent.
158+
159+A `path` might just be a series of fixed elements like `/foo/bar`, but some
160+elements might also be variable and encode atom auras, or some other format. For
161+example, you might like to include a date in the path like
162+`/updates/~2021.10.31..07.24.27..db68`. Other agents might create the path by
163+doing something like:
164+
165+```hoon
166+/update/(scot %da now.bowl)
167+```
168+
169+Then, when you get a subscription request, you might do something like:
170+
171+```hoon
172+?+ path (on-watch:def path)
173+ [%updates @ ~]
174+ =/ date=@da (slav %da i.t.path)
175+ ...(rest of code)...
176+```
177+
178+See the [Encoding in text](/docs/hoon/guides/strings#encoding-in-text) and
179+[Decoding from text](/docs/hoon/guides/strings#decoding-from-text) sections of
180+the Strings guide for more information on dealing with atoms encoded in strings.
181+
182+Aside from using function calls when constructing a `path` as demonstrated
183+above, you can also insert text you're previously stored with `=/` or what have
184+you, simply by enclosing them in brackets. For example, in the dojo:
185+
186+```
187+> =const 'bar'
188+> `path`/foo/[const]/baz
189+/foo/bar/baz
190+```
191+
192+## `wire`
193+
194+The type of a wire is formally defined as:
195+
196+```hoon
197++$ wire path
198+```
199+
200+So, a `wire` is just a [`path`](#path), type-wise they're exactly the same. The
201+reason there's a separate `wire` type is just to differentiate their purpose. A `wire` is a path for responses to requests an agent initiates. If you subscribe to the `path` `/some/path` on another agent, you also specify `/some/wire`. Then, when that agent sends out updates to subscribers of `/some/path`, your agent receives them on `/some/wire`.
202+
203+The `wire` is specified in the second argument of a `%pass` `card`. It's used
204+for anything you can `%pass`, such as `%poke`s, `%watch`es, and `%arvo` notes.
205+For example:
206+
207+```hoon
208+[%pass /this/is/wire %agent [~zod %foobar] %watch /this/is/path]
209+::
210+[%pass /this/is/wire %agent [~zod %foobar] %poke %foo !>('hello')]
211+::
212+[%pass /this/is/wire %arvo %b %wait (add now.bowl ~m1)]
213+```
214+
215+The `on-agent` and `on-arvo` arms of the agent core include a `wire` in their
216+respective sample. Responses from agents come in to the former, and responses
217+from vanes come in to the latter.