<commit_before>+++
title = "2. The Agent Core"
weight = 10
template = "doc.html"
+++

In this lesson we'll look at the basic type and structure of a Gall agent.

A Gall agent is a [door](/docs/glossary/door) with exactly ten [arms](/docs/glossary/arm). Each arm is responsible for
handling certain kinds of events that Gall feeds in to the agent. A door is
just a [core](/docs/glossary/core) with a sample - it's made with the
[barcab](/docs/hoon/reference/rune/bar#_-barcab) rune (`|_`) instead of the
usual [barcen](/docs/hoon/reference/rune/bar#-barcen) rune (`|%`).

## The ten arms

We'll discuss each of the arms in detail later. For now, here's a quick summary.
The arms of an agent can be be roughly grouped by purpose:

### State management

These arms are primarily for initializing and upgrading an agent.

- `on-init`: Handles starting an agent for the first time.
- `on-save`: Handles exporting an agent's state - typically as part of the
  upgrade process but also when suspending, uninstalling and debugging.
- `on-load`: Handles loading a previously exported agent state - typically as
  part of the upgrade process but also when resuming or reinstalling an agent.

### Request handlers

These arms handle requests initiated by outside entities, e.g. other agents,
HTTP requests from the front-end, etc.

- `on-poke`: Handles any calls that aren't subscriptions, i.e. one-time actions.
- `on-watch`: Handles subscription requests from other entities.
- `on-leave`: Handles unsubscribe requests from other, currently subscribed
  entities.

### Response handlers

These two arms handle responses to requests our agent previously initiated.

- `on-agent`: Handles subscription updates and request acknowledgements from
  other agents.
- `on-arvo`: Handles subscription updates, request acknowledgements, and
  responses from vanes.

### Scry handler

- `on-peek`: Handles local read-only requests.

### Failure handler

- `on-fail`: Handles certain kinds of crash reports from Gall. Most agents don't
  make use of this arm and just leave it with a basic default.

## Bowl

The sample of a Gall agent door is always a `bowl:gall`. Every time an event triggers the
agent, Gall populates the bowl with things like the current date-time, entropy,
subscription information, which ship the request came from, etc, so that all the
arms of the agent have access to that data. For the exact structure and contents
of the bowl, have a read through [its entry in the Gall vane types
documentation](/docs/arvo/gall/data-types#bowl).

## State

If you've worked through [Hoon School](/docs/hoon/hoon-school/intro), you may
recall that a core is a cell of `[battery payload]`. The battery is the core
itself compiled to Nock, and the payload is the subject which it operates on.

For an agent, the payload will at least contain the bowl, the usual Hoon and `zuse` standard
library functions, and the **state** of the agent. For example, if your agent
were for an address book app, it might keep a `map` of ships to address book
entries. It might add entries, delete entries, and modify entries. This address
book `map` would be part of the state stored in the payload.

## Transition function

If you recall from the prologue, the whole Arvo operating system works on the
basis of a simple transition function `(event, oldState) -> (effects, newState)`. Gall agents also function the same way. Eight of an agent's ten arms
produce the same thing, a cell of:

- **Head**: A list of effects called `card`s (which we'll discuss later).
- **Tail**: A new agent core, possibly with a modified payload.

It goes something like this:

1. An event is routed to Gall.
2. Gall calls the appropriate arm of the agent, depending on the kind of event.
3. That arm processes the event, returning a list `card`s to be sent off, and
   the agent core itself with a modified state in the payload.
4. Gall sends the `card`s off and saves the modified agent core.
5. Rinse and repeat.

## Virtualization

When a crash occurs in the kernel, the system usually aborts the computation and
discards the event as though it never happened. Gall on the other hand
virtualizes all its agents, so this doesn't happen. Instead, when a crash occurs
in an agent, Gall intercepts the crash and takes appropriate action depending on
the kind of event that caused it. For example, if a poke from another ship
caused a crash in the `on-poke` arm, Gall will respond to the poke with a
"nack", a negative acknowledgement, telling the original ship the poke was
rejected.

What this means is that you can intentionally design your agent to crash in
cases it can't handle. For example, if a poke comes in with an unexpected
`mark`, it crashes. If a permission check fails, it crashes. This is quite
different to most programs written in procedural languages, which must handle
all exceptions to avoid crashing.

## Example

Here's about the simplest valid Gall agent:

```hoon
|_  =bowl:gall
++  on-init   `..on-init
++  on-save   !>(~)
++  on-load   |=(vase `..on-init)
++  on-poke   |=(cage !!)
++  on-watch  |=(path !!)
++  on-leave  |=(path `..on-init)
++  on-peek   |=(path ~)
++  on-agent  |=([wire sign:agent:gall] !!)
++  on-arvo   |=([wire sign-arvo] !!)
++  on-fail   |=([term tang] `..on-init)
--
```

This is just a dummy agent that does absolutely nothing - it has no state and
rejects all messages by crashing. We'll get to what each of the arms do later.
For now, we'll just consider a few particular points.

Firstly, note its structure - it's a door (created with `|_`) with a sample of
`bowl:gall` and the ten arms described earlier.

Secondly, you'll notice some of the arms return:

```hoon
`..on-init
```

A backtick at the beginning is an irregular syntax meaning "prepend with null",
so for example, in the dojo:

```
> `50
[~ 50]
```

The next part has a dot-dot-arm syntax, which means "the parent core of the
specified arm". Since we've specified the arm as `on-init`, its parent is our
whole agent. In the [transition function](#transition-function) section we<commit_msg>gall-guide: 2-agent - clarify we'd usually cast to agent:gall<commit_after>+++
title = "2. The Agent Core"
weight = 10
template = "doc.html"
+++

In this lesson we'll look at the basic type and structure of a Gall agent.

A Gall agent is a [door](/docs/glossary/door) with exactly ten [arms](/docs/glossary/arm). Each arm is responsible for
handling certain kinds of events that Gall feeds in to the agent. A door is
just a [core](/docs/glossary/core) with a sample - it's made with the
[barcab](/docs/hoon/reference/rune/bar#_-barcab) rune (`|_`) instead of the
usual [barcen](/docs/hoon/reference/rune/bar#-barcen) rune (`|%`).

## The ten arms

We'll discuss each of the arms in detail later. For now, here's a quick summary.
The arms of an agent can be be roughly grouped by purpose:

### State management

These arms are primarily for initializing and upgrading an agent.

- `on-init`: Handles starting an agent for the first time.
- `on-save`: Handles exporting an agent's state - typically as part of the
  upgrade process but also when suspending, uninstalling and debugging.
- `on-load`: Handles loading a previously exported agent state - typically as
  part of the upgrade process but also when resuming or reinstalling an agent.

### Request handlers

These arms handle requests initiated by outside entities, e.g. other agents,
HTTP requests from the front-end, etc.

- `on-poke`: Handles any calls that aren't subscriptions, i.e. one-time actions.
- `on-watch`: Handles subscription requests from other entities.
- `on-leave`: Handles unsubscribe requests from other, currently subscribed
  entities.

### Response handlers

These two arms handle responses to requests our agent previously initiated.

- `on-agent`: Handles subscription updates and request acknowledgements from
  other agents.
- `on-arvo`: Handles subscription updates, request acknowledgements, and
  responses from vanes.

### Scry handler

- `on-peek`: Handles local read-only requests.

### Failure handler

- `on-fail`: Handles certain kinds of crash reports from Gall. Most agents don't
  make use of this arm and just leave it with a basic default.

## Bowl

The sample of a Gall agent door is always a `bowl:gall`. Every time an event triggers the
agent, Gall populates the bowl with things like the current date-time, entropy,
subscription information, which ship the request came from, etc, so that all the
arms of the agent have access to that data. For the exact structure and contents
of the bowl, have a read through [its entry in the Gall vane types
documentation](/docs/arvo/gall/data-types#bowl).

## State

If you've worked through [Hoon School](/docs/hoon/hoon-school/intro), you may
recall that a core is a cell of `[battery payload]`. The battery is the core
itself compiled to Nock, and the payload is the subject which it operates on.

For an agent, the payload will at least contain the bowl, the usual Hoon and `zuse` standard
library functions, and the **state** of the agent. For example, if your agent
were for an address book app, it might keep a `map` of ships to address book
entries. It might add entries, delete entries, and modify entries. This address
book `map` would be part of the state stored in the payload.

## Transition function

If you recall from the prologue, the whole Arvo operating system works on the
basis of a simple transition function `(event, oldState) -> (effects, newState)`. Gall agents also function the same way. Eight of an agent's ten arms
produce the same thing, a cell of:

- **Head**: A list of effects called `card`s (which we'll discuss later).
- **Tail**: A new agent core, possibly with a modified payload.

It goes something like this:

1. An event is routed to Gall.
2. Gall calls the appropriate arm of the agent, depending on the kind of event.
3. That arm processes the event, returning a list `card`s to be sent off, and
   the agent core itself with a modified state in the payload.
4. Gall sends the `card`s off and saves the modified agent core.
5. Rinse and repeat.

## Virtualization

When a crash occurs in the kernel, the system usually aborts the computation and
discards the event as though it never happened. Gall on the other hand
virtualizes all its agents, so this doesn't happen. Instead, when a crash occurs
in an agent, Gall intercepts the crash and takes appropriate action depending on
the kind of event that caused it. For example, if a poke from another ship
caused a crash in the `on-poke` arm, Gall will respond to the poke with a
"nack", a negative acknowledgement, telling the original ship the poke was
rejected.

What this means is that you can intentionally design your agent to crash in
cases it can't handle. For example, if a poke comes in with an unexpected
`mark`, it crashes. If a permission check fails, it crashes. This is quite
different to most programs written in procedural languages, which must handle
all exceptions to avoid crashing.

## Example

Here's about the simplest valid Gall agent:

```hoon
|_  =bowl:gall
++  on-init   `..on-init
++  on-save   !>(~)
++  on-load   |=(vase `..on-init)
++  on-poke   |=(cage !!)
++  on-watch  |=(path !!)
++  on-leave  |=(path `..on-init)
++  on-peek   |=(path ~)
++  on-agent  |=([wire sign:agent:gall] !!)
++  on-arvo   |=([wire sign-arvo] !!)
++  on-fail   |=([term tang] `..on-init)
--
```

This is just a dummy agent that does absolutely nothing - it has no state and
rejects all messages by crashing. Typically we'd cast this to an `agent:gall`,
but in this instance we won't so it's easier to examine its structure in the
dojo. We'll get to what each of the arms do later. For now, we'll just consider
a few particular points.

Firstly, note its structure - it's a door (created with `|_`) with a sample of
`bowl:gall` and the ten arms described earlier.

Secondly, you'll notice some of the arms return:

```hoon
`..on-init
```

A backtick at the beginning is an irregular syntax meaning "prepend with null",
so for example, in the dojo:

```
> `50
[~ 50]
```

The next part has a dot-dot-arm syntax, which means "the parent core of the
specified arm". Since we've specified the arm as `on-init`, its parent is our
whole agent. In the [transition function](#transition-function) section we
{'fraction_non_alphanumeric': 0.0860302488209465, 'fraction_numerical': 0.0020328508700601725, 'mean_word_length': 4.0077361563517915, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, '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': '1359502', 'n_tokens_mistral': 3608, 'n_tokens_neox': 3428, 'n_words': 1847}