HTTP Notifier
This page is the internal module map for core/http-notifier.ts and its
six channel classes. For the full durable-approval design — checkpoints,
resumption, security caveats — see Human in the
Loop instead; this is where those senders live in
the source tree.
resolveHttpNotifier(config) reads AgentConfig.httpNotifier and builds
whichever channel-specific sender its channel discriminant names,
returning an approver/questionHandler/onRunStart/onRunFinish
bundle — only ever consulted for the http channel; cli/http_stream
keep the library's own live defaults untouched. Resolved once per
AgentConfig object and cached in a WeakMap, since it's called on
every runAgent()/resumeAgent() turn.
Setting one up
AgentConfig.httpNotifier is only ever consulted on the http channel
— set it on the agent whose approvals/questions/lifecycle events need to
reach somewhere durable:
import type { AgentConfig, HttpNotifierConfig } from 'loopengine'
const webhookUrl = process.env.MY_AGENT_WEBHOOK_URL
const webhookSecret = process.env.MY_AGENT_WEBHOOK_SECRET
const httpNotifier: HttpNotifierConfig | undefined =
webhookUrl && webhookSecret
? {
channel: 'webhook', // or 'slack' | 'lark' | 'email' | 'database' | 'redis'
config: { webhookUrl, webhookSecret },
events: ['approval', 'question', 'run_start', 'run_finish'],
}
: undefined
export const config: AgentConfig = {
// ...
httpNotifier,
}
(agents/customer-service/index.ts's real version — only set when the
agent's own webhook env vars are actually configured; unset, it falls
straight through to the library's own live defaults on every channel,
including http.) events picks which of the four event kinds this
notifier actually receives — 'database'/'redis' are restricted to
'approval' alone at the type level, see below.
Six channels, one file each under core/http-notify-triggers/:
channel |
Class | Notes |
|---|---|---|
'webhook' |
WebhookNotifier |
Signed HMAC-SHA256 POST — X-Actauth-Signature for an approval, X-Askuser-Signature for a question. |
'slack' |
SlackNotifier |
chat.postMessage with interactive buttons. |
'lark' |
LarkNotifier |
Lark/Feishu's own card API. |
'email' |
EmailNotifier |
A sendEmail callback plus a signed, expiring magic-link token per link. |
'database' |
DatabaseApprover |
Writes a row for a separate worker/dashboard to poll — approval-only. |
'redis' |
RedisQueueApprover |
Pushes a queue entry — approval-only. |
'database'/'redis' aren't notification channels at all — nothing
gets told anything, a human or worker just polls directly — so
AgentConfig.ApprovalOnlyHttpNotifierEvent restricts both to the
'approval' event at the type level. Chat channels (slack/lark)
share one formatChatLifecycleMessage helper for
onRunStart/onRunFinish, since a lifecycle event has no signed
payload to react to — just a plain announcement string; email reuses
the same text as its message body under its own subject line.