# `Issho.Inbox`
[🔗](https://github.com/hattoriai/issho/blob/v0.4.0/lib/issho/inbox.ex#L1)

What was said to someone while they were away: each comment that
mentions them, in any room, kept until they have read it. An agent
that was not in the room when a person wrote "@Claude, a look?" finds
it here when it next comes (the `inbox` tool), and the app can wake it
at once (`:on_mention`).

A comment that mentions someone (`"comment.created"`, its `mentions`)
lands in the inbox of each it mentions, but its author; so does an
app's own event with `mentions` in its data (`Issho.Events.emit/4`).
An edit that adds a mention does not: the inbox is of what was said to
them, once.

    {:ok, items} = Issho.Inbox.items(MyApp.Issho, assistant, on_behalf_of: ada)
    :ok = Issho.Inbox.mark_read(MyApp.Issho, assistant, Enum.map(items, & &1["id"]))

An item is the event as `Issho.Event.to_map/1` gives it (`"name"`,
`"room"`, `"document"`, `"by"`, `"data"`, `"at"`), with its `"id"`
and whether it was `"read"`. Its room's policy decides, when it is
read, whether its reader may still see it (`:read`): one whose access
was taken away does not.

An inbox is a document of Issho's (`document/1`), kept by the
instance's store as the rooms' documents are, and never opened in a
room. It keeps the last 200 items.

## Waking an agent

MCP has no way to reach an agent that is not connected. So, for each
mention, Issho:

  * calls the instance's `:on_mention`, `{module, function}` or a
    function of two arguments, with the key mentioned and the item, in
    a process of its own: the app starts its agent (a job, a webhook,
    a chat message to its owner);
  * tells the connected MCP clients that the `issho://inbox` resource
    changed (`Issho.MCP`), and its server's instructions say to read
    the inbox at the start of a session.

## In a cluster

An event is delivered once in the cluster: on the node where the
comment was saved, after it was, or where the app emitted its event.

# `item`

```elixir
@type item() :: map()
```

An item: an event that mentioned its reader, with its id and whether it was read.

# `document`

```elixir
@spec document(String.t()) :: String.t()
```

The document of the inbox of the actor with this key.

# `items`

```elixir
@spec items(atom(), Issho.Actor.t() | Issho.Identity.t(), keyword()) ::
  {:ok, [item()]} | {:error, term()}
```

The items of an actor's inbox, newest first: those not read yet, or
all with `all: true`; only those of rooms the policy lets it `:read`.
`actor` is an actor or an `Issho.Identity`. Options: `:all`,
`:limit` (50), and `:on_behalf_of` and `:claims`, for the policy.

# `mark_read`

```elixir
@spec mark_read(
  atom(),
  Issho.Actor.t() | Issho.Identity.t() | String.t(),
  [String.t()] | :all
) ::
  :ok | {:error, term()}
```

Marks items of an inbox read, by their ids, or all of them with `:all`:
the inbox of an actor, an `Issho.Identity`, or a key.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
