You activate channels per-task via
notify=:
notify= — the queue is the operator’s source of truth.
Notify-string format
notify= is a list of strings, each prefixed by the channel:
Multiple notifications fire in parallel — slow Slack API calls don’t block email.
Dashboard
Always on. Operators log in at/login, see their task queue, click in to fill the form. The dashboard reads the same task data the SDK created — there’s nothing channel-specific about it.
By default a non-operator user sees only tasks routed to them. Operators see everything.
Why not webhooks-as-channels?
We deliberately don’t expose “raw webhook” as a channel —notify=["webhook:https://..."] isn’t a thing. The reason: the channel layer owns the human-facing UI generation. A webhook destination has no UI to render; you’d be implementing one ad-hoc on the receiving end. If you want webhook delivery for a system (not a human), use the callback_url= parameter, which fires on every terminal status transition. That’s how the Temporal and LangGraph adapters get their signals.
Adding a custom channel
Channels live inserver/channels/. A channel module exports:
- A
notify_task(task_id, task_title, notify, form_definition, ...)function — called fromBackgroundTasksafter task creation - A webhook route under
/api/channels/<your-channel>/...that handles inbound messages
server/channels/slack/ and server/channels/email/ for the canonical examples. New channels are a Phase-2 community contribution surface — see the contribution guide.