REFERENCE
SDK 範例
@asgard-js/core 與 @asgard-js/react 的用法與可以直接操作的範例。
Headless
如果內建的 <Chatbot> 不符合你的設計,你可以完全跳過它,直接用
useChannel hook 自己組 UI。下方範例的對話介面 100% 自製,
連 SDK 的 CSS 都沒有引入。
範例程式
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 [input, setInput] = useState("");
const messages = conversation
? Array.from(conversation.messages.values())
: [];
const submit = () => {
const text = input.trim();
if (!text || isConnecting) return;
sendMessage?.({ text });
setInput("");
};
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;
})}
<input
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyDown={(e) => {
if (e.key === "Enter" && !e.nativeEvent.isComposing) {
e.preventDefault();
submit();
}
}}
placeholder="輸入訊息…"
/>
<button onClick={submit} disabled={!input.trim() || isConnecting}>
送出
</button>
</div>
);
}useChannel回傳值欄位 說明 conversation目前的 Conversation,包含一個 messages MapsendMessage送出訊息(支援 text/payload/blobIds)resetChannel重置 channel 並建立新對話 closeChannel關閉 SSE 連線 channelTitle目前的對話標題( null= 未命名),隨後端title.update更新isConnecting是否正在連線 isResetting是否正在重置 channel 訊息類型
所有訊息都統一為
ConversationMessage,在 render 時用type區分:user— 使用者送出的訊息bot— 機器人回覆。bot.message.template是 SDK 內建模板資料;串流文字在bot.typingText,完整文字在bot.message.texttool-call— Agent 工具呼叫thinking— 延伸思考(reasoning)區塊:thinking.text為思考內容,thinking.isThinking區分串流中/已完成subagent— 子代理生命週期:subagent.kind(start/complete)、status、summaryerror— 連線或執行錯誤
衍生狀態 hooks(任務 / 子代理 / 標題)
除了自己走訪
conversation.messages,@asgard-js/react另外提供三個 hook,把Channel上的響應式衍生狀態橋接進useSyncExternalStore,只在該切片變動時 re-render:useTaskList(channel)→Task[](任務清單,見 任務清單)useSubagents(channel)→Subagent[](子代理清單,見 子代理清單)useChannelTitle(channel)→string | null(對話標題,見 對話標題)
框架無關的底層 API 則由
@asgard-js/core提供:createDerivedStores(conversation$)、deriveTasks(conversation)、deriveSubagents(conversation)。