Skip to Content
Chat Quickstart (Docs-Only)

Chat Quickstart (Docs-Only)

This page mirrors the smaller examples/chat-with-ai flow using only documented @kalamdb/client and @kalamdb/consumer APIs:

  • createClient, Auth.basic
  • query, live
  • createConsumerClient(), runConsumer()

This path is for local development without external auth setup.

Prerequisites

  • Node.js >= 18
  • running KalamDB server
  • a user that can run SQL and consume topic messages

Install:

bash snippetBASH
npm i @kalamdb/client @kalamdb/consumer

1) Create a client

ts snippetTS
import { createClient, Auth } from '@kalamdb/client';import { createConsumerClient, runConsumer } from '@kalamdb/consumer'; const client = createClient({  url: 'http://localhost:2900',  authProvider: async () => Auth.basic('admin', 'AdminPass123!'),}); const worker = createConsumerClient({  url: 'http://localhost:2900',  authProvider: async () => Auth.basic('admin', 'AdminPass123!'),});

2) Apply chat schema + topic

ts snippetTS
await client.query('CREATE NAMESPACE IF NOT EXISTS chat_demo'); await client.query(`CREATE SHARED TABLE chat_demo.messages (  id         BIGINT PRIMARY KEY DEFAULT SNOWFLAKE_ID(),  room       TEXT NOT NULL DEFAULT 'main',  role       TEXT NOT NULL,  author     TEXT NOT NULL,  content    TEXT NOT NULL,  created_at TIMESTAMP DEFAULT NOW())`); await client.query('CREATE TOPIC chat_demo.ai_inbox');await client.query(`ALTER TOPIC chat_demo.ai_inboxADD SOURCE chat_demo.messagesON INSERTWITH (payload = 'full')`);

3) Start the worker with runConsumer()

ts snippetTS
await runConsumer<Record<string, unknown>>({  client: worker,  name: 'chat-demo-agent',  topic: 'chat_demo.ai_inbox',  groupId: 'chat-demo-agent',  onChange: async (ctx, change) => {    const row = change.data;    if (String(row.role ?? '') !== 'user') {      return;    }     const room = String(row.room ?? 'main');    const content = String(row.content ?? '').trim();    if (!content) {      return;    }     const reply = `AI reply: KalamDB stored "${content}" and this worker wrote the response.`;     await ctx.sql(      'INSERT INTO chat_demo.messages (room, role, author, content) VALUES ($1, $2, $3, $4)',      [room, 'assistant', 'KalamDB Copilot', reply],    );  },});

4) Subscribe in the chat client

Use live() so the UI always receives the latest materialized row set.

ts snippetTS
const room = 'main'; const unsubscribe = await client.live(  `SELECT * FROM chat_demo.messages   WHERE room = '${room}'`,  (rows) => {    // This callback receives the current chat timeline after KalamDB has    // already reconciled inserts and updates for you.    renderRows(rows);  },  {    limit: 200,    subscriptionOptions: { last_rows: 200 },  },);

If you switch this table to WITH (TYPE = 'USER'), the same query text still works for every user and KalamDB will only return that authenticated user’s rows.

Insert a user message:

ts snippetTS
await client.query(  'INSERT INTO chat_demo.messages (room, role, author, content) VALUES ($1, $2, $3, $4)',  [room, 'user', 'demo-user', 'hello'],);

5) Cleanup

ts snippetTS
await unsubscribe();await client.disconnect();

Next

Last updated on