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

What an agent is doing in a room, seen by the people in it, and their
hand on it: a task, its steps and how far it is, and Pause, Resume and
Stop.

    {:ok, claude} = Issho.Agents.join(MyApp.Issho, agent, "board:42", on_behalf_of: ada)

    :ok = Issho.Work.start(claude, "Plan the release", ["Read the board", "Group the cards", "Write the summary"])
    :ok = Issho.Work.progress(claude, "Read the board", :done)
    :ok = Issho.Work.finish(claude, "Grouped 14 cards in 3 columns.")

The task is in the agent's state in the room (`"task"`, see
`Issho.Awareness`), so each page shows it as it goes
(`Issho.Components.agents/1`), and each start and finish is an event of
the room (`"agent.started"`, `"agent.finished"`). Agents that reach your
app over MCP do the same with the `start_task`, `progress` and
`finish_task` tools.

## Pause, Resume, Stop

The person an agent acts for may pause, resume or stop it in a room,
and so may anyone your policy allows `:interrupt` (`Issho.Policy`). A
paused or stopped agent changes nothing more in the room: its next
transaction is refused (`{:error, {:interrupted, ...}}`), and its next
tool call, but those that only read, says who paused or stopped it and
what to do. A transaction is whole: what the agent changed before is
there, nothing is half done. A paused agent waits for `"agent.resumed"`;
a stopped one finishes (`finish/2` lets it go on in another task).
Each is an event of the room: `"agent.interrupted"` (`data`: `%{agent:
key, action: "pause" | "stop"}`) and `"agent.resumed"`, by the person
who did it.

An agent whose work runs under Issho (`Issho.Agents.run/5`) is stopped
at once: its work ends wherever it is. One that crashes says so
(`failed/2`).

## What is yours

Issho keeps the task, its state and its events; it decides nothing of
what a page shows of them. `Issho.Components.agents/1` is a default, to
use or to leave: the task is in each agent's state in the room
(`Issho.Awareness`), and its events are the room's (`Issho.Events`), to
draw your own way.

# `action`

```elixir
@type action() :: :pause | :resume | :stop
```

# `step_state`

```elixir
@type step_state() :: :pending | :active | :done | :skipped
```

# `failed`

```elixir
@spec failed(GenServer.server(), term()) :: :ok
```

Says the agent's work failed: its task, if it has one, is `"failed"`,
and the room hears `"agent.failed"` (`data`: `%{agent: key, title:
title, reason: kind}`). The people in the room learn only the kind of
failure (`"error"`, `"timeout"`, `"killed"` or `"exit"`), not its
details, which may say more than they should know; your app has them
in the `[:issho, :agent, :failed]` telemetry event (metadata `:room`,
`:agent`, `:reason`), to log or to tell in its own words.

`Issho.Agents.run/5` calls it when the work it runs crashes; call it
yourself for a work that fails another way.

# `finish`

```elixir
@spec finish(GenServer.server(), String.t() | nil) :: :ok | {:error, term()}
```

Finishes the task, with a few words of what was done; a stop is over with it.

# `interrupt`

```elixir
@spec interrupt(atom(), String.t(), String.t(), action(), keyword()) :: :ok
```

Pauses, resumes or stops the agent `key` in a room, for `by` (an actor
or an identity), from your server: no policy is asked. From a person's
page, the agents bar does it through their session, under the policy.

# `progress`

```elixir
@spec progress(
  GenServer.server(),
  String.t() | non_neg_integer() | nil,
  step_state(),
  keyword()
) ::
  :ok | {:error, term()}
```

Says how far the task is: a step (its label or its index) is `:done`
(the next one pending becomes active), `:active`, `:skipped` or
`:pending`. Options: `:add`, more steps at the end; `:note`, a few words
of where it is.

# `start`

```elixir
@spec start(GenServer.server(), String.t(), [String.t()]) :: :ok | {:error, term()}
```

Starts a task: its title and its steps (labels; the first is active).
A task the agent had is replaced. A paused agent starts none until it
is resumed (`{:error, {:interrupted, ...}}`); a stopped one may.

---

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