<commit_before>+++
title = "Gall Apps"
weight = 8
template = "doc.html"
aliases = ["/docs/learn/arvo/gall/"]
+++

This document describes Gall, the Arvo userspace vane. It is accurate as of 2019.12.02.

# Agents

Urbit code lives in the following basic categories:

- Runtime (Nock interpreter, persistence engine, IO drivers, jets)
- Kernel vanes (managed by Arvo)
- Userspace agents (managed by Gall, permanent state)
- Userspace imps (managed by Spider, transient state)

This lays out the framework for the third category:  Agents.

An agent is a piece of software that is primarily focused on maintaining
and distributing a piece of state with a defined structure.  It exposes
an interface that lets programs read, subscribe to, and manipulate the
state.  Every event happens in an atomic transaction, so the state is
never inconsistent.  Since the state is permanent, when the agent is
upgraded with a change to the structure of the state, the developer
provides a migration function from the old state type to the new state
type.

It's not too far off to think of an agent as simply a database with
developer-defined logic.  But an agent is significantly less constrained
than a database.  Databases are usually tightly constrained in one or
more ways because they need to provide certain guarantees (like
atomicity) or optimizations (like indexes).  Urbit is a single-level
store, so atomicity comes for free.  Many applications don't use
databases because they need relational indices; rather, they use them
for their guarantees around persistence.  Some do need the indices,
though, and it's not hard to imagine an agent which provides a SQL-like
interface.

On the other hand, an agent is also a lot like what many systems call a
"service".   An agent is permanent and addressable -- a running program
can talk to an agent just by naming it. An agent can perform IO, unlike
most databases.  This is a critical part of an agent:  it performs IO
along the same transaction boundaries as changes to its state, so if an
effect happens, you know that the associated state change has happened.
You should be careful, though, to avoid creating implicit non-atomicity
-- eg if it comes into an inconsistent state pending a response to an IO
action.

But the best way to think about an agent is as a state machine.  Like a
state machine, any input could happen at any time, and it must react
coherently to that input.  Ouput (effects) and the next state of the
machine are both pure functions of the previous state and the input
event.  Of course, it's important to ensure there isn't an order of
events that could cause your agent to enter an inconsistent state.

We often think of state machines as finite state machines, but of course
in this instance, the state is not actually finite (though it should be
definable in a regular recursive data type).  

## Specification

An agent is defined as a [core](/docs/glossary/core/) with a set of [arms](/docs/glossary/arm/) to handle various
events.  These handlers usually produce a list of effects and the next
state of the agent.  The interface definition can be found in
`sys/zuse.hoon`, which at the time of writing is:

```hoon
++  agent
  =<  form
  |%
  +$  step  (quip card form)
  +$  card  (wind note gift)
  +$  note
    $%  [%arvo =note-arvo]
        [%agent [=ship name=term] =task]
    ==
  +$  task
    $%  [%watch =path]
        [%watch-as =mark =path]
        [%leave ~]
        [%poke =cage]
        [%poke-as =mark =cage]
    ==
  +$  gift
    $%  [%fact path=(unit path) =cage]
        [%kick path=(unit path) ship=(unit ship)]
        [%watch-ack p=(unit tang)]
        [%poke-ack p=(unit tang)]
    ==
  +$  sign
    $%  [%poke-ack p=(unit tang)]
        [%watch-ack p=(unit tang)]
        [%fact =cage]
        [%kick ~]
    ==
  ++  form
    $_  ^|
    |_  bowl
    ++  on-init
      *(quip card _^|(..on-init))
    ::
    ++  on-save
      *vase
    ::
    ++  on-load
      |~  old-state=vase
      *(quip card _^|(..on-init))
    ::
    ++  on-poke
      |~  [mark vase]
      *(quip card _^|(..on-init))
    ::
    ++  on-watch
      |~  path
      *(quip card _^|(..on-init))
    ::
    ++  on-leave
      |~  path
      *(quip card _^|(..on-init))
    ::
    ++  on-peek
      |~  path
      *(unit (unit cage))
    ::
    ++  on-agent
      |~  [wire sign]
      *(quip card _^|(..on-init))
    ::
    ++  on-arvo
      |~  [wire sign-arvo]
      *(quip card _^|(..on-init))
    ::
    ++  on-fail
      |~  [term tang]
      *(quip card _^|(..on-init))
    --
```

Here's a skeleton example of an implementation:

```hoon
^-  agent:gall
=|  state=@
|_  bowl:gall
+*  this  .
++  on-init
  `this
::
++  on-save
  !>(state)
::
++  on-load
  |=  =old-state=vase
  =/  old-state  !<(@ old-state-vase)
  ?~  old-state
    ~&  %prep-lost
    `this
  ~&  %prep-found
  `this(state u.old-state)
::
++  on-poke
  |=  [=mark =vase]
  ~&  state=state
  ~&  got-poked-with-data=mark]<commit_msg>Corrects ++on-load example code in gall tutorial<commit_after>+++
title = "Gall Apps"
weight = 8
template = "doc.html"
aliases = ["/docs/learn/arvo/gall/"]
+++

This document describes Gall, the Arvo userspace vane. It is accurate as of 2019.12.02.

# Agents

Urbit code lives in the following basic categories:

- Runtime (Nock interpreter, persistence engine, IO drivers, jets)
- Kernel vanes (managed by Arvo)
- Userspace agents (managed by Gall, permanent state)
- Userspace imps (managed by Spider, transient state)

This lays out the framework for the third category:  Agents.

An agent is a piece of software that is primarily focused on maintaining
and distributing a piece of state with a defined structure.  It exposes
an interface that lets programs read, subscribe to, and manipulate the
state.  Every event happens in an atomic transaction, so the state is
never inconsistent.  Since the state is permanent, when the agent is
upgraded with a change to the structure of the state, the developer
provides a migration function from the old state type to the new state
type.

It's not too far off to think of an agent as simply a database with
developer-defined logic.  But an agent is significantly less constrained
than a database.  Databases are usually tightly constrained in one or
more ways because they need to provide certain guarantees (like
atomicity) or optimizations (like indexes).  Urbit is a single-level
store, so atomicity comes for free.  Many applications don't use
databases because they need relational indices; rather, they use them
for their guarantees around persistence.  Some do need the indices,
though, and it's not hard to imagine an agent which provides a SQL-like
interface.

On the other hand, an agent is also a lot like what many systems call a
"service".   An agent is permanent and addressable -- a running program
can talk to an agent just by naming it. An agent can perform IO, unlike
most databases.  This is a critical part of an agent:  it performs IO
along the same transaction boundaries as changes to its state, so if an
effect happens, you know that the associated state change has happened.
You should be careful, though, to avoid creating implicit non-atomicity
-- eg if it comes into an inconsistent state pending a response to an IO
action.

But the best way to think about an agent is as a state machine.  Like a
state machine, any input could happen at any time, and it must react
coherently to that input.  Ouput (effects) and the next state of the
machine are both pure functions of the previous state and the input
event.  Of course, it's important to ensure there isn't an order of
events that could cause your agent to enter an inconsistent state.

We often think of state machines as finite state machines, but of course
in this instance, the state is not actually finite (though it should be
definable in a regular recursive data type).  

## Specification

An agent is defined as a [core](/docs/glossary/core/) with a set of [arms](/docs/glossary/arm/) to handle various
events.  These handlers usually produce a list of effects and the next
state of the agent.  The interface definition can be found in
`sys/zuse.hoon`, which at the time of writing is:

```hoon
++  agent
  =<  form
  |%
  +$  step  (quip card form)
  +$  card  (wind note gift)
  +$  note
    $%  [%arvo =note-arvo]
        [%agent [=ship name=term] =task]
    ==
  +$  task
    $%  [%watch =path]
        [%watch-as =mark =path]
        [%leave ~]
        [%poke =cage]
        [%poke-as =mark =cage]
    ==
  +$  gift
    $%  [%fact path=(unit path) =cage]
        [%kick path=(unit path) ship=(unit ship)]
        [%watch-ack p=(unit tang)]
        [%poke-ack p=(unit tang)]
    ==
  +$  sign
    $%  [%poke-ack p=(unit tang)]
        [%watch-ack p=(unit tang)]
        [%fact =cage]
        [%kick ~]
    ==
  ++  form
    $_  ^|
    |_  bowl
    ++  on-init
      *(quip card _^|(..on-init))
    ::
    ++  on-save
      *vase
    ::
    ++  on-load
      |~  old-state=vase
      *(quip card _^|(..on-init))
    ::
    ++  on-poke
      |~  [mark vase]
      *(quip card _^|(..on-init))
    ::
    ++  on-watch
      |~  path
      *(quip card _^|(..on-init))
    ::
    ++  on-leave
      |~  path
      *(quip card _^|(..on-init))
    ::
    ++  on-peek
      |~  path
      *(unit (unit cage))
    ::
    ++  on-agent
      |~  [wire sign]
      *(quip card _^|(..on-init))
    ::
    ++  on-arvo
      |~  [wire sign-arvo]
      *(quip card _^|(..on-init))
    ::
    ++  on-fail
      |~  [term tang]
      *(quip card _^|(..on-init))
    --
```

Here's a skeleton example of an implementation:

```hoon
^-  agent:gall
=|  state=@
|_  bowl:gall
+*  this  .
++  on-init
  `this
::
++  on-save
  !>(state)
::
++  on-load
  |=  =old-state=vase
  =/  old-state  !<(@ old-state-vase)
  ?~  old-state
    ~&  %prep-lost
    `this
  ~&  %prep-found
  `this(state old-state)
::
++  on-poke
  |=  [=mark =vase]
  ~&  state=state
  ~&  got-poked-with-data=mark]
{'fraction_non_alphanumeric': 0.10737581535373808, 'fraction_numerical': 0.0018063221274460613, 'mean_word_length': 2.80817730225449, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6019024', 'n_tokens_mistral': 3249, 'n_tokens_neox': 3123, 'n_words': 1307}