Sending a message
This example sends a message to a bot provider over the Asgard REST API and reads the response.
The endpoint
POST {{base_url}}/generic/ns/{{namespace}}/bot-provider/{{bot_provider_name}}/message/sse
About customChannelId
customChannelId identifies a conversation, and it is what keeps the memory of a session together. Send several messages with the same customChannelId and the bot remembers what came before. To start a new conversation, use a different one.
cURL
curl -X POST "https://api.asgard-ai.com/generic/ns/your-namespace/bot-provider/your-bot-provider/message/sse" \
-H "Content-Type: application/json" \
-H "X-API-KEY: your-api-key" \
-d '{
"customChannelId": "channel-001",
"customMessageId": "msg-001",
"text": "How do I reset my password?",
"action": "NONE"
}'
JavaScript (fetch)
const BASE_URL = 'https://api.asgard-ai.com';
const NAMESPACE = 'your-namespace';
const BOT_PROVIDER = 'your-bot-provider';
const API_KEY = process.env.ASGARD_API_KEY;
async function sendMessage(channelId, messageId, text) {
const url = `${BASE_URL}/generic/ns/${NAMESPACE}/bot-provider/${BOT_PROVIDER}/message/sse`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-KEY': API_KEY,
},
body: JSON.stringify({
customChannelId: channelId,
customMessageId: messageId,
text: text,
action: 'NONE',
}),
});
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
// read the SSE stream and accumulate the full response
const reader = response.body.getReader();
const decoder = new TextDecoder();
let fullText = '';
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value, { stream: true });
const lines = chunk.split('\n');
for (const line of lines) {
if (!line.startsWith('data:')) continue;
const jsonStr = line.slice(5).trim();
if (!jsonStr) continue;
try {
const event = JSON.parse(jsonStr);
if (event.eventType === 'asgard.message.delta') {
fullText += event.fact.messageDelta.message.text;
}
if (event.eventType === 'asgard.message.complete') {
console.log('Full response:', fullText);
}
if (event.eventType === 'asgard.run.done') {
console.log('Request complete');
return fullText;
}
} catch (e) {
// ignore a line that will not parse
}
}
}
return fullText;
}
// usage
sendMessage('channel-001', 'msg-001', 'How do I reset my password?')
.then((reply) => console.log('Bot reply:', reply))
.catch(console.error);
Python (requests)
import requests
import json
import os
BASE_URL = "https://api.asgard-ai.com"
NAMESPACE = "your-namespace"
BOT_PROVIDER = "your-bot-provider"
API_KEY = os.environ.get("ASGARD_API_KEY")
def send_message(channel_id: str, message_id: str, text: str) -> str:
url = f"{BASE_URL}/generic/ns/{NAMESPACE}/bot-provider/{BOT_PROVIDER}/message/sse"
headers = {
"Content-Type": "application/json",
"X-API-KEY": API_KEY,
}
payload = {
"customChannelId": channel_id,
"customMessageId": message_id,
"text": text,
"action": "NONE",
}
full_text = ""
with requests.post(url, headers=headers, json=payload, stream=True) as response:
response.raise_for_status()
for line in response.iter_lines():
if not line:
continue
decoded = line.decode("utf-8")
if not decoded.startswith("data:"):
continue
json_str = decoded[5:].strip()
if not json_str:
continue
try:
event = json.loads(json_str)
event_type = event.get("eventType")
if event_type == "asgard.message.delta":
text_chunk = event["fact"]["messageDelta"]["message"]["text"]
full_text += text_chunk
elif event_type == "asgard.message.complete":
print(f"Full response: {full_text}")
elif event_type == "asgard.run.done":
print("Request complete")
break
except json.JSONDecodeError:
pass
return full_text
if __name__ == "__main__":
reply = send_message("channel-001", "msg-001", "How do I reset my password?")
print(f"Bot reply: {reply}")
The response events
After you send a message, the API returns a series of events as an SSE (Server-Sent Events) stream:
| Event type | What it is |
|---|---|
asgard.run.init | The request initialises, carrying the runId and other details |
asgard.message.delta | A piece of the message, which is what produces the typewriter effect |
asgard.message.complete | The complete message, with the template render data |
asgard.run.done | The request ends and the stream closes |
For the detailed event format see the SSE response events.
Next
- Handling a streamed response — building the typewriter effect and a live streaming interface
- Querying a knowledge base — question and answer against a RAG knowledge base