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