# subscribe

> Declares that a workflow state waits on an event, and configures the wait — who may hold it, who may hand it on, whether it is armed at all, and what must be satisfied first. A subscribe holds CONFIG only: the routes that fire when the event arrives live at the state level, and the SLA promises live in its own Assigned/Finished blocks.

<!-- id: workflow-subscribe · area: workflow · stability: stable · html: https://osysharp.com/reference/workflow/subscribe/ -->

## Summary        {#summary}
`subscribe` declares that a workflow state is listening for an event, and configures that wait — who may fill it, when
it is armed, what must hold first, and what it promises. It is **config only**: the guarded routes that fire when the
event arrives (`on Event when (…) { … goto … }`) live at the **state** level alongside the wait, not inside the
`subscribe` block.

## Signature      {#signature}
```osy syntax
subscribe <Event>(<typed params>) [as <Alias>] [foreach (<T> <x> in <collection>)] {
  Candidates = <principal => bool> | <() => List<Principal>>;   // who may HOLD or satisfy it
  Reassign   = <actor => bool>;                                 // who may hand it ON
  Assignee   = <expr>;                                          // who it is handed to at arm time
  When       = <predicate>;                                     // whether it is armed on this run at all
  After      = [<Slot>, …];                                     // slots that must be satisfied first

  Assigned { … }   // the pickup promise — Within, Remind, a breach arm
  Finished { … }   // the completion promise
  Requires { … }   // named preconditions on filling it
}

subscribe <Event>();   // bodyless — a wait with no configuration
```

## Description    {#description}
A workflow state advances when an event it subscribes to arrives and a matching route transitions it. `subscribe`
names that event and restates its typed parameters (so the payload is visible at the handler), then configures the
wait itself. Each setting has its own page — see [See also](#see-also) — and the shape to hold is that they answer
different questions:

| setting | question |
|---|---|
| [`Candidates`](https://osysharp.com/reference/workflow/candidates/) | who may **hold or satisfy** this slot |
| [`Reassign`](https://osysharp.com/reference/workflow/assign/) | who besides the holder may **move** it |
| `Assignee` | who it belongs to from the moment it is armed (a slot with one is not a pool slot) |
| `When` | whether this run gets the slot **at all** |
| [`After`](https://osysharp.com/reference/workflow/slot-dependencies/) | which sibling slots must be satisfied before it opens |

The **promises** — how long a slot may sit unclaimed, how long its holder has, the nudges along the way, the retries,
and where a missed one routes — are declared in the [`Assigned`/`Finished`](https://osysharp.com/reference/workflow/milestone/) blocks inside the
slot, not as flat settings on it. That is where `Within`, `Remind`, `Retries`, `Backoff` and the `Unassigned` /
`Unfinished` / `Exhausted` arms live.

A slot's **success** routes (`on <Event> when (…)`, `on <Alias>(…)`) and the state's own timers (`on Expire`,
`on Deadline`) live at the **state** level, not inside the `subscribe` — every `on …` in one place.

An **entity-typed parameter is a live row, not a copy**. A route may read it and write through it, exactly as it can
through the workflow's own tracked item, and those writes are saved with the rest of the transition:

```osy title="an event that carries the row it is about" syntax app=order-fulfillment
event CustomerWithdrawsItem(OrderItem item);

on CustomerWithdrawsItem(OrderItem item) {
  item.Status = ItemStatus.Withdrawn;    // persisted with the transition
  RefundItem(item);
}
```

The event's delivery context (who deposited, the claim) is available to a route that opts into a `Deposit`
parameter — see <span class="planned" title="this page is planned and not written yet">workflow-route</span>; it is never ambient.

A state may hold more than one `subscribe` (multi-wait / N-of-M); that is its own surface — see <span class="planned" title="this page is planned and not written yet">workflow-multiwait</span>.

## Examples       {#examples}
A pool slot the support team may take, a supervisor may move, and which promises to be picked up within an hour:

```osy title="a pool slot with a gate, a hand-over rule and a promise" syntax
subscribe Respond() as Reply {
  Candidates = u => u.Team == Team.Support && u.OnDuty;
  Reassign   = a => a.IsSupervisor;

  Assigned { Within = TimeSpan.FromHours(1); Unassigned { goto Escalated; } }
}
```

The same wait as an app writes it, in context:

```osy title="a guarded approval wait" syntax sample=wf-approvals/model/po_approval.osy#draft-state
  state Draft {
    subscribe Submit();
    on Submit { goto Review; }
  }
```

Minimal — a wait with no config, just the event:

```osy title="minimal" syntax app=order-fulfillment
subscribe Submit();
```

## See also       {#see-also}
- [Candidates (slot)](https://osysharp.com/reference/workflow/candidates/) — the slot's `Candidates` gate: who may HOLD/satisfy this slot (predicate or computed
  set), and how a screen ASKS it before offering a button: `<Wf>.For(item).<Slot>.Candidates(u)`
- [Assign — handing a slot to a named colleague](https://osysharp.com/reference/workflow/assign/) — `Reassign`, and the verbs that hand a slot to a named colleague
- [Assigned / Finished (milestones)](https://osysharp.com/reference/workflow/milestone/) — the `Assigned`/`Finished` promises declared inside the slot: `Within`, `Remind`, `Retries`,
  `Backoff`, and the breach arms
- [slot dependencies (After / When / Pending)](https://osysharp.com/reference/workflow/slot-dependencies/) — `After`: the sibling slots that must be satisfied before this one opens
- [Requires — named preconditions, and the live checklist](https://osysharp.com/reference/workflow/requires/) — `Requires`: named preconditions on filling the slot, and the live checklist that reports them
- <span class="planned" title="this page is planned and not written yet">workflow-event</span> — the `event` this subscribes to (a method signature)
- <span class="planned" title="this page is planned and not written yet">workflow-route</span> — the state-level `on <Event> … goto …` routes that consume the deposit
- <span class="planned" title="this page is planned and not written yet">workflow-state</span> — the enclosing state and its `Expire` deadline
- [Tracks and Initial (the field a workflow drives)](https://osysharp.com/reference/workflow/tracks/) — how the workflow binds to an entity's enum property
