Core API Reference
@asgard-js/core provides the low-level SSE client, channel management,
and conversation model. If you use the <Chatbot> component, these are
already wrapped for you. If you use
Headless mode to build your own UI, you'll
work with these APIs directly.
AsgardServiceClient
The core SSE connection manager. Handles connections, event dispatch, and file uploads.
Constructor
import { AsgardServiceClient } from "@asgard-js/core";
const client = new AsgardServiceClient({
botProviderEndpoint: "https://api.asgard-ai.com/ns/{namespace}/bot-provider/{id}",
apiKey: "optional-api-key",
customHeaders: { Authorization: "Bearer ..." },
debugMode: false,
});
Methods
| Method | Signature | Description |
|---|---|---|
on | on<K>(event: K, listener: SseEvents[K]): void | Register an event listener. Only the last listener per event is kept |
fetchSse | fetchSse(payload: FetchSsePayload, options?: FetchSseOptions): void | Initiate an SSE streaming request |
uploadFile | uploadFile(file: File, channelId: string): Promise<BlobUploadResponse> | Upload a file to the Blob API |
close | close(): void | Close all connections and clean up resources |
ClientConfig
| Field | Type | Description |
|---|---|---|
botProviderEndpoint | string | Required. Bot provider base URL |
endpoint | string | botProviderEndpoint |
apiKey | string | Static API key |
customHeaders | Record<string, string> | Custom HTTP headers |
debugMode | boolean | Enable debug logging |
transformSsePayload | (payload) => payload | Transform SSE payload before sending |
onRunInit | EventHandler | INIT event handler |
onMessage | EventHandler | MESSAGE event handler |
onToolCall | EventHandler | TOOL_CALL event handler |
onProcess | EventHandler | PROCESS event handler |
onRunDone | EventHandler | DONE event handler |
onRunError | EventHandler | ERROR event handler |
FetchSsePayload
{
customChannelId: string;
customMessageId?: string;
text: string;
payload?: Record<string, unknown> | (() => Record<string, unknown>);
action: FetchSseAction; // RESET_CHANNEL | NONE
blobIds?: string[];
}
FetchSseOptions
{
delayTime?: number; // Delay between events in ms, default 50
onSseStart?: () => void;
onSseMessage?: (response: SseResponse<EventType>) => void;
onSseError?: (error: unknown) => void;
onSseCompleted?: () => void;
}
Channel
Manages the SSE lifecycle for a single conversation channel. Created via static factory methods.
Creation
import { Channel, Conversation } from "@asgard-js/core";
const conversation = new Conversation({ messages: new Map() });
// Option 1: Create without reset (preserve history)
const channel = Channel.create({
client,
customChannelId: "user-123",
conversation,
statesObserver: (states) => {
console.log(states.isConnecting, states.conversation);
},
});
// Option 2: Create and reset (start fresh)
const channel = await Channel.reset(
{ client, customChannelId: "user-123", conversation },
{ text: "Hello" }, // Optional initial message
);
Static Methods
| Method | Signature | Description |
|---|---|---|
create | static create(config: ChannelConfig): Channel | Create a channel without sending reset |
reset | static async reset(config, payload?, options?): Promise<Channel> | Create a channel and send RESET_CHANNEL |
Instance Methods
| Method | Signature | Description |
|---|---|---|
sendMessage | sendMessage(payload, options?): Promise<void> | Send a user message (supports text / payload / blobIds / filePreviewUrls) |
close | close(): void | Close the channel and clean up subscriptions |
ChannelConfig
| Field | Type | Description |
|---|---|---|
client | AsgardServiceClient | SSE client instance |
customChannelId | string | Unique channel ID |
customMessageId | string | Custom message ID (optional) |
conversation | Conversation | Initial conversation object |
statesObserver | (states: ChannelStates) => void | State change observer |
ChannelStates
{ isConnecting: boolean; conversation: Conversation }
Conversation
Immutable conversation model. Every state change returns a new
Conversation instance.
Constructor
import { Conversation } from "@asgard-js/core";
const conversation = new Conversation({
messages: new Map(), // or null
});
Properties
| Property | Type | Description |
|---|---|---|
messages | Map<string, ConversationMessage> | null | All messages, keyed by messageId |
Methods
| Method | Description |
|---|---|
pushMessage(message) | Add a message, returns a new Conversation |
onMessage(response) | Process an SSE event, auto-dispatches by eventType, returns a new Conversation |
onMessage dispatches internally based on eventType:
| EventType | Behavior |
|---|---|
MESSAGE_START | Create a new bot message (isTyping: true) |
MESSAGE_DELTA | Append to typingText (streaming text) |
MESSAGE_COMPLETE | Finalize the message (isTyping: false, full message written) |
TOOL_CALL_START | Create a tool-call message (isComplete: false) |
TOOL_CALL_COMPLETE | Update tool-call result (isComplete: true) |
ERROR | Create an error message |
EventType
All SSE event types:
enum EventType {
INIT = "asgard.run.init"
PROCESS_START = "asgard.process.start"
PROCESS_COMPLETE = "asgard.process.complete"
MESSAGE_START = "asgard.message.start"
MESSAGE_DELTA = "asgard.message.delta"
MESSAGE_COMPLETE = "asgard.message.complete"
TOOL_CALL_START = "asgard.tool_call.start"
TOOL_CALL_COMPLETE = "asgard.tool_call.complete"
DONE = "asgard.run.done"
ERROR = "asgard.run.error"
}
When listening, use aggregate events:
| Aggregate Event | Includes |
|---|---|
PROCESS | PROCESS_START + PROCESS_COMPLETE |
MESSAGE | MESSAGE_START + MESSAGE_DELTA + MESSAGE_COMPLETE |
TOOL_CALL | TOOL_CALL_START + TOOL_CALL_COMPLETE |
ConversationMessage
A union of four message types, discriminated by the type field:
user
{ type: "user"; messageId: string; text: string;
blobIds?: string[]; filePreviewUrls?: string[];
documentNames?: string[]; time: Date; traceId?: string }
bot
{ type: "bot"; messageId: string; eventType: EventType;
isTyping: boolean; typingText: string | null;
message: Message; time: Date; traceId?: string; raw: string }
tool-call
{ type: "tool-call"; messageId: string;
eventType: EventType.TOOL_CALL_START | EventType.TOOL_CALL_COMPLETE;
processId: string; callSeq: number; toolName: string;
toolsetName: string; parameter: Record<string, unknown>;
result?: Record<string, unknown>; isComplete: boolean;
time: Date; traceId?: string }
error
{ type: "error"; messageId: string; eventType: EventType;
error: ErrorMessage; time: Date; traceId?: string }
HttpError
import { HttpError, isHttpError } from "@asgard-js/core";
try { /* ... */ } catch (err) {
if (isHttpError(err)) {
console.log(err.status, err.statusText, err.body);
}
}
| Property | Type | Description |
|---|---|---|
status | number | HTTP status code |
statusText | string | Status text |
body | unknown | Response body |