channel / components / channel-composer
ChannelComposer
The simplest way to think about it: the box your users type in — and the only piece wired to your own endpoint. Pick a channel, write, hit Enter. The composer POSTs to your send route; delivery and persistence happen server-side, and the timeline updates reactively.
Preview
This preview actually works — type something and send it. It posts to this site's demo endpoint, exactly like it would post to yours.
Install
pnpm dlx shadcn@latest add https://registry.ekairos.dev/r/channel-composer.jsonStart simple: one channel, one endpoint
The minimum is an endpoint. With a single channel (the default is ["web"]) there's no picker — just the textarea and the send button. Enter sends, Shift+Enter makes a new line:
import { ChannelComposer } from "@/components/ekairos/channel/channel-composer";
<ChannelComposer endpoint="/api/channel/send" contextId={thread.contextId} />Then: multiple channels
Pass more than one channel and a badge picker appears above the textarea — the user chooses where the message goes out:
Finally: wire it to your endpoint
This is the one piece of custom code your app owns. The composer sends a single JSON POST, and your route calls the channel domain server-side (and triggers the agent reaction if you want one):
POST /api/channel/send
content-type: application/json
{
"channel": "whatsapp",
"text": "Tomo el pedido: 200 cascos IRAM 3620.",
"contextId": "ctx_...", // optional
"threadKey": "thread_..." // optional
}A non-2xx response rejects the send and fires onError; on success the textarea clears and onSent fires with the channel and text. The full server-side recipe lives in the send guide below.
Props
| prop | type | description |
|---|---|---|
| endpoint * | string | Your send route. Receives POST { channel, text, contextId?, threadKey? } as JSON. |
| contextId | string | Agent context the message belongs to; forwarded in the POST body. |
| threadKey | string | Thread key forwarded in the POST body. |
| channels | string[] | Channels the user can send through. Default: ["web"]. More than one shows the badge picker. |
| placeholder | string | Textarea placeholder. Default: "Send a message". |
| onSent | ({ channel, text }) => void | Called after a successful send. |
| onError | (error: Error) => void | Called when the endpoint fails or the request throws. |
| className | string | Extra classes for the form. |