Skip to main content

REFERENCE

SDK Demos

How to use @asgard-js/core and @asgard-js/react, with demos you can try on the page.

Headless

If the built-in <Chatbot> doesn't fit your design, skip it entirely and build your own UI on top of the useChannel hook. The chat panel below is 100% custom — none of the SDK's stylesheets are imported.

  1. Example​

    import { useMemo, useState } from "react";
    import { AsgardServiceClient } from "@asgard-js/core";
    import { useChannel } from "@asgard-js/react";

    export function HeadlessChat() {
    const client = useMemo(
    () =>
    new AsgardServiceClient({
    botProviderEndpoint: "https://...",
    }),
    [],
    );

    const { conversation, sendMessage, isConnecting } = useChannel({
    client,
    customChannelId: "my-channel",
    defaultIsOpen: true,
    });

    const messages = conversation
    ? Array.from(conversation.messages.values())
    : [];

    return (
    <div>
    {messages.map((msg) => {
    if (msg.type === "user") return <div key={msg.messageId}>{msg.text}</div>;
    if (msg.type === "bot") return <div key={msg.messageId}>{msg.message?.text}</div>;
    if (msg.type === "tool-call")
    return <div key={msg.messageId}>🔧 {msg.toolName}</div>;
    return null;
    })}
    {/* Your own input → sendMessage({ text }) */}
    </div>
    );
    }
  2. useChannel Return Value​

    FieldDescription
    conversationCurrent Conversation containing a messages Map
    sendMessageSend a message (supports text / payload / blobIds)
    resetChannelReset the channel and start a new conversation
    closeChannelClose the SSE connection
    channelTitleCurrent channel title (null = unnamed); updates from the backend title.update event
    isConnectingWhether the channel is connecting
    isResettingWhether the channel is resetting
  3. Message Types​

    All messages share the ConversationMessage union — branch on type when rendering:

    • user — sent by the user
    • bot — bot reply. bot.message.template carries the built-in SDK template; streaming text is on bot.typingText, the full text is on bot.message.text
    • tool-call — agent tool invocation
    • thinking — extended-thinking (reasoning) block: thinking.text holds the content, thinking.isThinking distinguishes streaming vs. completed
    • subagent — subagent lifecycle: subagent.kind (start / complete), status, summary
    • error — connection or runtime error
  4. Derived-State Hooks (tasks / subagents / title)​

    Besides walking conversation.messages yourself, @asgard-js/react also exposes three hooks that bridge the reactive derived-state stores on Channel into useSyncExternalStore, re-rendering only when that slice changes:

    The framework-agnostic building blocks live in @asgard-js/core: createDerivedStores(conversation$), deriveTasks(conversation), deriveSubagents(conversation).

Ready to get started?

Want to see how Asgard fits your team? Talk to us.

Contact us