Human approval layer for your mission critical AI workflows
A unified typescript SDK for human-in-the-loop
npm i @hitl-sdk/hitlclaude "Follow this guide: https://hitl-sdk.dev/onboard.md"The Chat Platform Agnostic
The Workflow Engine Agnostic
The Persistence Agnostic
Human-in-the-loop as code
Human oversight as code — easy to integrate into any workflow, easy to build automation people can trust.
One await
Replace polling, queues, and resume logic with a single await.
- No polling
- No queues
- No custom retry logic
const approvalId = crypto.randomUUID();
await db.approvals.insert({
id: approvalId,
status: "pending",
leadEmail: input.email,
draft: input.draft,
expiresAt: addHours(new Date(), 72),
});
await slack.postMessage({
channel: "#sales",
text: `Inbound lead: ${input.email}`,
blocks: buildApprovalBlocks(approvalId),
});
await queue.enqueue("approval.poll", { approvalId }, {
repeat: { every: "15m" },
attempts: 288,
});
// workflow pauses here — resume via cron/webhook
let row = await db.approvals.findById(approvalId);
while (row.status === "pending") {
if (row.expiresAt < new Date()) {
await db.approvals.update(approvalId, { status: "expired" });
return;
}
await sleep(POLL_INTERVAL_MS);
row = await db.approvals.findById(approvalId);
}
if (row.status !== "approved") return;
const edits = await db.approvalEdits.findByApprovalId(approvalId);
await sendEmail({
to: input.email,
subject: edits?.subject ?? input.draft.subject,
body: edits?.body ?? input.draft.body,
});const approval = await waitForHuman({
message: `Inbound lead: ${input.email}`,
actions: actions()
.approve({ fields: { subject, body } })
.build(),
timeout: "72h",
});
if (isResolved(approval, "approve")) {
await sendEmail({ ...approval.feedbacks });
}One waitForHuman,
tons of patterns
Editable approve, deny with reason, and custom actions — all in one call.
- Approve with editable fields
- Deny with a reason
- Custom actions for any workflow
const approval = await waitForHuman({
message: `Draft email to ${input.email} ready for your review.`,
actions: actions()
.approve({
label: "Review and send",
fields: {
subject: field.textField({ label: "Subject", default: draft.subject }),
body: field.textArea({ label: "Body", default: draft.body }),
},
})
.deny({ fields: { reason: field.textArea({ label: "Reason" }) } })
.build(),
});remind or escalate
at any time
Keep following up in-thread or on another channel — on your schedule.
- Remind after an hour
- Every weekday morning
- Escalate when it's time
import { remind, escalate } from "@hitl-sdk/hitl";
const approval = await waitForHuman({
message: "Approve expense report?",
actions,
timeout: "72h",
reminders: [
remind.after("1h", { message: "Still waiting for approval" }),
remind.weekdaysAt("07:00", { tz: "UTC", message: "Morning reminder" }),
escalate.to("oncall").after("2d"),
],
});Keep humans in the loop, wherever they work
AI handles the work. Humans make the calls. Integrates with Vercel's Chat SDK — all within Slack, Microsoft Teams, and Discord.
Slack
Approve without leaving the channels and threads where your team already collaborates.
Microsoft Teams
Sign off inside Teams — right where chats and handoffs already happen.
Discord
Drop AI drafts into your server channels and let your team review in place.
Web UI
Embed approvals into your web app. Inbox API is included in the SDK.
Your durable agent stack.
No lock-in.
HITL sdk plugs into the tools you already use.
npm i @hitl-sdk/hitlAI Agent layer
Claude, GPT, Kimi, and more. Build your own AI agents.
npm i @workflow/ai aiChat layer
Deliver approvals to Slack, Teams, Discord, and every chat platform.
npm i @hitl-sdk/adapter-chat-sdkWorkflow layer
Pick your workflow engine. Make workflows durable.
npm i @hitl-sdk/resolver-workflow-sdknpm i @hitl-sdk/resolver-inngestnpm i @hitl-sdk/resolver-temporalPersistent layer
Pick your database. Wait years for approval.
npm i @hitl-sdk/state-pgnpm i @hitl-sdk/state-sqlitenpm i @hitl-sdk/state-ioredisTry now
Create your first approval flow today.
npm i @hitl-sdk/hitlclaude "Follow this guide: https://hitl-sdk.dev/onboard.md"