Skip to main content

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​

MethodSignatureDescription
onon<K>(event: K, listener: SseEvents[K]): voidRegister an event listener. Only the last listener per event is kept
fetchSsefetchSse(payload: FetchSsePayload, options?: FetchSseOptions): voidInitiate an SSE streaming request
uploadFileuploadFile(file: File, channelId: string): Promise<BlobUploadResponse>Upload a file to the Blob API
closeclose(): voidClose all connections and clean up resources

ClientConfig​

FieldTypeDescription
botProviderEndpointstringRequired. Bot provider base URL
endpointstringDeprecated — use botProviderEndpoint
apiKeystringStatic API key
customHeadersRecord<string, string>Custom HTTP headers
debugModebooleanEnable debug logging
transformSsePayload(payload) => payloadTransform SSE payload before sending
onRunInitEventHandlerINIT event handler
onMessageEventHandlerMESSAGE event handler
onToolCallEventHandlerTOOL_CALL event handler
onProcessEventHandlerPROCESS event handler
onRunDoneEventHandlerDONE event handler
onRunErrorEventHandlerERROR 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​

MethodSignatureDescription
createstatic create(config: ChannelConfig): ChannelCreate a channel without sending reset
resetstatic async reset(config, payload?, options?): Promise<Channel>Create a channel and send RESET_CHANNEL

Instance Methods​

MethodSignatureDescription
sendMessagesendMessage(payload, options?): Promise<void>Send a user message (supports text / payload / blobIds / filePreviewUrls)
closeclose(): voidClose the channel and clean up subscriptions

ChannelConfig​

FieldTypeDescription
clientAsgardServiceClientSSE client instance
customChannelIdstringUnique channel ID
customMessageIdstringCustom message ID (optional)
conversationConversationInitial conversation object
statesObserver(states: ChannelStates) => voidState 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​

PropertyTypeDescription
messagesMap<string, ConversationMessage> | nullAll messages, keyed by messageId

Methods​

MethodDescription
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:

EventTypeBehavior
MESSAGE_STARTCreate a new bot message (isTyping: true)
MESSAGE_DELTAAppend to typingText (streaming text)
MESSAGE_COMPLETEFinalize the message (isTyping: false, full message written)
TOOL_CALL_STARTCreate a tool-call message (isComplete: false)
TOOL_CALL_COMPLETEUpdate tool-call result (isComplete: true)
ERRORCreate 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 EventIncludes
PROCESSPROCESS_START + PROCESS_COMPLETE
MESSAGEMESSAGE_START + MESSAGE_DELTA + MESSAGE_COMPLETE
TOOL_CALLTOOL_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);
}
}
PropertyTypeDescription
statusnumberHTTP status code
statusTextstringStatus text
bodyunknownResponse body