HIL Policies
A HilPolicy (Human-in-the-Loop Policy) controls whether a field appears in a
human reviewer's task inbox, how it is displayed, and what level of interaction is allowed.
Structure
public sealed class HilPolicy
{
public bool SendToHil { get; init; } = false;
public HilDisplayMode DisplayMode { get; init; } = HilDisplayMode.Concealed;
public HilInputMode InputMode { get; init; } = HilInputMode.Locked;
public string Label { get; init; } = string.Empty;
public string Description { get; init; } = string.Empty;
}
SendToHil — Master Switch
When false, the field is invisible to humans in any review or task flow,
regardless of other settings. This is the first decision for any field.
| Set to true | Set to false |
|---|---|
| Approval strategy, actors list, email recipient, message body, form title | Credentials, internal IDs, system-generated outputs (message IDs, response bodies), infrastructure config (host, port) |
DisplayMode
Controls how the field value is rendered in the HIL interface.
Concealed
The field is not rendered. Even if SendToHil: true, the value is hidden.
Use as a safe default when you want a field to be editable but not pre-show its value.
ReadableContext
The field value is displayed to the reviewer as readable information. Whether they can change
it depends on InputMode.
Use for: Context fields — the human must understand the value to make an informed decision.
- Approval strategy (so the approver understands the voting rules)
- Assigned actors (so each approver knows who else is involved)
- Email recipient (so the reviewer knows where the email is going)
- Form title (heading shown at the top of the inbox task)
ReadableMasked
The field value is displayed but partially obscured. Used when the full value would be a privacy concern but the reviewer needs to confirm the right entity is targeted.
Examples: employee ID (show last 4 digits), account number (show partially masked).
InputMode
Controls whether and how the human can modify the field value.
Locked
Read-only. The reviewer sees the value (if ReadableContext) but cannot change it.
Use when: Context-only — informs the reviewer but they have no authority to change it. Examples: approval strategy, form title, escalation user.
EditableOptional
Pre-filled with the computed value. The reviewer may optionally change it before continuing. If unchanged, the original value is used.
Use when: The template produces a good default but exceptional overrides are allowed. Examples: email recipient, Slack channel, HTTP URL.
PrefilledEditable
Like EditableOptional, but the UI presents the field in an active editing state —
the reviewer is explicitly prompted to review and edit it, not just allowed to.
Use when: Content is dynamically generated and the reviewer's judgment on the specific content matters. Examples: AI-generated Slack message, auto-drafted email subject.
RequiredFromHuman
The field is pre-filled but the human must explicitly confirm or provide a value before the workflow can continue. The HIL interface will not allow submission without this field being actively reviewed.
Use when: Passive acceptance is not sufficient — the human must consciously take responsibility. Examples: email body (confirm before sending), financial amount, approval decision.
Label & Description
| Property | Purpose | Best practice |
|---|---|---|
Label | Short field name shown in inbox | 1–3 words, human-friendly. Falls back to camelCase FieldId if not set. |
Description | Tooltip or helper text below the field | One sentence explaining what to do. "Review and confirm the message body before it is sent." |
Decision Matrix
| Human needs to… | SendToHil | DisplayMode | InputMode |
|---|---|---|---|
| Not see this field at all | false | Concealed | Locked |
| See it — context only, no change | true | ReadableContext | Locked |
| See it and optionally change it | true | ReadableContext | EditableOptional |
| See it and actively review/edit | true | ReadableContext | PrefilledEditable |
| Must confirm or provide a value | true | ReadableContext | RequiredFromHuman |
| See partial value (privacy) | true | ReadableMasked | Locked |
HIL and Suspension
HIL policies are most meaningful when the node suspends and routes a task to a human actor's
inbox. The SuspensionPolicy controls the waiting behaviour; HilPolicy
controls the rendering of each field in the inbox task. See
Suspension Policies for the timing and deadline side.
Examples
// Approval strategy — context only, cannot change
HilPolicy = new HilPolicy
{
SendToHil = true,
DisplayMode = HilDisplayMode.ReadableContext,
InputMode = HilInputMode.Locked,
Label = "Approval Strategy",
Description = "How votes are counted to reach a decision."
}
// Email body — must confirm before sending
HilPolicy = new HilPolicy
{
SendToHil = true,
DisplayMode = HilDisplayMode.ReadableContext,
InputMode = HilInputMode.RequiredFromHuman,
Label = "Email Body",
Description = "Read the full message and confirm it is correct before sending."
}
// Slack message — pre-filled, actively prompted to personalise
HilPolicy = new HilPolicy
{
SendToHil = true,
DisplayMode = HilDisplayMode.ReadableContext,
InputMode = HilInputMode.PrefilledEditable,
Label = "Message",
Description = "Review and optionally personalise this message before it is posted."
}
// Credential — completely hidden
HilPolicy = new HilPolicy
{
SendToHil = false,
DisplayMode = HilDisplayMode.Concealed,
InputMode = HilInputMode.Locked,
Label = "Credential",
Description = "Internal vault reference — not shown to reviewers."
}