Notifications
Send contextual messages to the reviewer's channel without creating a new approval step. Use notify for updates while a request is pending, or to keep a conversation thread across multiple human steps.
Import
import { notify } from "@/lib/hitl-client";notify
Signature
notify(notification: NotifyOptions): Promise<TimelineAnchor>Options
NotifyOptions is a discriminated union of three shapes:
Anchor to a prior step (after)
notify({
after: HumanPending | HumanBatchPending | HumanResult | TimelineAnchor,
message: string,
channel?: string,
detail?: Record<string, unknown>,
})Posts in the same chat thread as the referenced step. Most common pattern after requestHuman.
Anchor by id (on)
notify({
on: string, // human request or batch id
message: string,
channel?: string,
detail?: Record<string, unknown>,
})Use when you have an id but not the full pending object (e.g. from stored context).
Standalone
notify({
message: string,
channel?: string,
detail?: Record<string, unknown>,
})Delivers to the default channel without threading.
| Field | Type | Description |
|---|---|---|
message | string | Notification body shown in the channel |
after | pending / result / anchor | Thread under this step |
on | string | Request or batch id when after is unavailable |
detail | Record<string, unknown> | Opaque metadata (not shown to reviewer by default) |
channel | string | Adapter id or adapter_id:destination; defaults to first configured adapter |
Returns
TimelineAnchor ({ id, externalRef }). Use as after on a subsequent requestHuman or waitForHuman call to keep threading.
Example
import { actions } from "@hitl-sdk/hitl";
import { requestHuman, notify, waitForHuman } from "@/lib/hitl-client";
const pending = await requestHuman({
message: `Say hello to ${name}?`,
actions: actions().approve({ label: "Approve" }).deny({ label: "Deny" }).build(),
});
await notify({
after: pending,
message: `Context for ${name}`,
detail: { requestedAt: new Date().toISOString() },
});
const response = await waitForHuman(pending);TimelineAnchor
Pending handles, resolved results, and notify return values all implement TimelineAnchor:
interface TimelineAnchor {
id: string;
externalRef: string;
}| Field | Description |
|---|---|
id | Hitl request or batch id |
externalRef | Adapter-native message ref (empty string when none) |
Pass any anchor as after on requestHuman, waitForHuman, or notify to post in the same channel thread.
Thread chaining
Chain pending steps, notifications, and resolved results in one conversation thread.
While pending
Post context after creating a request, before waiting:
const pending = await requestHuman({ message: "Approve expense?", actions });
await notify({ after: pending, message: "Receipt attached in thread" });
const result = await waitForHuman(pending, { timeout: "72h" });Multi-step approvals
Post a follow-up request in the same chat thread after a resolved step:
const first = await waitForHuman({ message: "Initial review?", actions });
const second = await requestHuman({
message: "Follow-up: any changes needed?",
actions,
after: first,
});
const followUp = await waitForHuman(second);After resolution
Notify after a resolved step, then start a follow-up request in the same thread:
const first = await waitForHuman({ message: "Approve draft?", actions });
await notify({
after: first,
message: "Draft was approved. Scheduling send for tomorrow.",
});
const second = await requestHuman({
message: "Confirm send time?",
actions,
after: first,
});See also
- Human steps: create and wait for approvals
- Foundations overview: API map