channel / quickstart
Multichannel in four steps.
1 — Install and push the schema
pnpm add @ekairos/channel @ekairos/agent
npx instant-cli@latest push schemaThe channel domain composes the events domain, so pushing agentDomain (which includes channel) gives you everything:
import { agentDomain } from "@ekairos/agent/schema";
export default agentDomain.toInstantSchema();domain("app").includes(agentDomain).withSchema({...}). Your entities and the channel entities live in the same InstantDB app — that is what makes the UI plug & play.2 — Boot the platforms
import { createChannels } from "@ekairos/channel/platforms";
import { db } from "@/lib/db"; // InstantDB admin client
export const channels = await createChannels({
db,
userName: "ekairos",
platforms: {
slack: {
botToken: process.env.SLACK_BOT_TOKEN!,
signingSecret: process.env.SLACK_SIGNING_SECRET!,
},
telegram: { botToken: process.env.TELEGRAM_BOT_TOKEN! },
},
resolveContextId: async ({ channel, threadKey }) => {
// one platform conversation = one agent thread
const thread = await ensureThread({ key: `${channel}:${threadKey}` });
return thread.contextId;
},
react: async (inbound) => {
const reaction = await reactOnThread(inbound.contextId, inbound.message);
return reaction.text; // posted back on the same platform, persisted outbound
},
});Each configured platform needs its adapter package installed once (pnpm add @chat-adapter/slack, etc.) — they are optional peers, so you only carry the platforms you use. Credentials and per-platform setup live in Platform setup.
3 — Mount the webhook
import { channels } from "@/lib/channels";
export async function POST(
request: Request,
{ params }: { params: Promise<{ platform: string }> },
) {
const { platform } = await params;
const handler = channels.webhooks[platform];
if (!handler) {
return new Response("unknown platform", { status: 404 });
}
return handler(request);
}One route serves every platform. Point each platform's webhook URL at /api/channels/<platform> and the inbound pipeline is live: message → canonical record → agent reaction → reply.
4 — Render the timeline
pnpm dlx shadcn@latest add https://registry.ekairos.dev/r/channel-timeline.json"use client";
import { db } from "@/lib/db.client"; // InstantDB react client
import { ChannelTimeline } from "@/components/ekairos/channel/channel-timeline";
export function ThreadConversation({ contextId }: { contextId: string }) {
return <ChannelTimeline db={db} contextId={contextId} />;
}No fetch, no API route, no props plumbing: the component queries channel_messages reactively. A whatsapp reply appears in the timeline the moment the webhook persists it.
5 — (Optional) Send from your product
Outbound from the UI is the one endpoint you own — see Send messages. Drop in ChannelComposer and point it at that endpoint.