curl -X POST "http://localhost:5001/event" \
-H "Content-Type: application/json" \
-d '{
"client_msg_no": "msg_001_stream_start",
"channel_id": "group_ai_chat",
"channel_type": 2,
"from_uid": "ai_assistant",
"event": {
"type": "___TextMessageStart",
"data": "{\"type\":1,\"content\":\"Starting AI response...\"}"
}
}'
curl -X POST "http://localhost:5001/event" \
-H "Content-Type: application/json" \
-d '{
"client_msg_no": "msg_001_stream_start",
"channel_id": "group_ai_chat",
"channel_type": 2,
"from_uid": "ai_assistant",
"event": {
"type": "___TextMessageContent",
"data": "Hello! How can I help you today?"
}
}'
curl -X POST "http://localhost:5001/event" \
-H "Content-Type: application/json" \
-d '{
"client_msg_no": "msg_001_stream_start",
"channel_id": "group_ai_chat",
"channel_type": 2,
"from_uid": "ai_assistant",
"event": {
"type": "___TextMessageEnd",
"data": ""
}
}'
curl -X POST "http://localhost:5001/event" \
-H "Content-Type: application/json" \
-d '{
"client_msg_no": "custom_event_001",
"channel_id": "user_123",
"channel_type": 1,
"from_uid": "system",
"event": {
"type": "user_status_update",
"timestamp": 1640995200000,
"data": "{\"status\": \"online\", \"last_seen\": 1640995200000}"
}
}'
// Streaming text message example
const streamId = `stream_${Date.now()}`;
// 1. Start stream
await fetch('http://localhost:5001/event', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
client_msg_no: streamId,
channel_id: 'group_ai_chat',
channel_type: 2,
from_uid: 'ai_assistant',
event: {
type: '___TextMessageStart',
data: 'Starting AI response...'
}
})
});
// 2. Send content
await fetch('http://localhost:5001/event', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
client_msg_no: streamId,
channel_id: 'group_ai_chat',
channel_type: 2,
from_uid: 'ai_assistant',
event: {
type: '___TextMessageContent',
data: 'Hello! How can I help you today?'
}
})
});
// 3. End stream
await fetch('http://localhost:5001/event', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
client_msg_no: streamId,
channel_id: 'group_ai_chat',
channel_type: 2,
from_uid: 'ai_assistant',
event: {
type: '___TextMessageEnd',
data: ''
}
})
});
import requests
import time
# Streaming text message example
stream_id = f"stream_{int(time.time() * 1000)}"
base_url = "http://localhost:5001/event"
# 1. Start stream
requests.post(base_url, json={
"client_msg_no": stream_id,
"channel_id": "group_ai_chat",
"channel_type": 2,
"from_uid": "ai_assistant",
"event": {
"type": "___TextMessageStart",
"data": "Starting AI response..."
}
})
# 2. Send content
requests.post(base_url, json={
"client_msg_no": stream_id,
"channel_id": "group_ai_chat",
"channel_type": 2,
"from_uid": "ai_assistant",
"event": {
"type": "___TextMessageContent",
"data": "Hello! How can I help you today?"
}
})
# 3. End stream
requests.post(base_url, json={
"client_msg_no": stream_id,
"channel_id": "group_ai_chat",
"channel_type": 2,
"from_uid": "ai_assistant",
"event": {
"type": "___TextMessageEnd",
"data": ""
}
})
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"time"
)
type Event struct {
Type string `json:"type"`
Data string `json:"data"`
Timestamp int64 `json:"timestamp,omitempty"`
}
type EventRequest struct {
ClientMsgNo string `json:"client_msg_no"`
ChannelID string `json:"channel_id"`
ChannelType int `json:"channel_type"`
FromUID string `json:"from_uid"`
Event Event `json:"event"`
}
func sendEvent(req EventRequest) error {
jsonData, _ := json.Marshal(req)
resp, err := http.Post(
"http://localhost:5001/event",
"application/json",
bytes.NewBuffer(jsonData),
)
if err != nil {
return err
}
defer resp.Body.Close()
return nil
}
func main() {
streamID := fmt.Sprintf("stream_%d", time.Now().UnixMilli())
// 1. Start stream
sendEvent(EventRequest{
ClientMsgNo: streamID,
ChannelID: "group_ai_chat",
ChannelType: 2,
FromUID: "ai_assistant",
Event: Event{
Type: "___TextMessageStart",
Data: "Starting AI response...",
},
})
// 2. Send content
sendEvent(EventRequest{
ClientMsgNo: streamID,
ChannelID: "group_ai_chat",
ChannelType: 2,
FromUID: "ai_assistant",
Event: Event{
Type: "___TextMessageContent",
Data: "Hello! How can I help you today?",
},
})
// 3. End stream
sendEvent(EventRequest{
ClientMsgNo: streamID,
ChannelID: "group_ai_chat",
ChannelType: 2,
FromUID: "ai_assistant",
Event: Event{
Type: "___TextMessageEnd",
Data: "",
},
})
}
{
"status": "ok"
}
Event Management
Send Event
Send various types of events to channels, including streaming text messages and custom events
POST
/
event
curl -X POST "http://localhost:5001/event" \
-H "Content-Type: application/json" \
-d '{
"client_msg_no": "msg_001_stream_start",
"channel_id": "group_ai_chat",
"channel_type": 2,
"from_uid": "ai_assistant",
"event": {
"type": "___TextMessageStart",
"data": "{\"type\":1,\"content\":\"Starting AI response...\"}"
}
}'
curl -X POST "http://localhost:5001/event" \
-H "Content-Type: application/json" \
-d '{
"client_msg_no": "msg_001_stream_start",
"channel_id": "group_ai_chat",
"channel_type": 2,
"from_uid": "ai_assistant",
"event": {
"type": "___TextMessageContent",
"data": "Hello! How can I help you today?"
}
}'
curl -X POST "http://localhost:5001/event" \
-H "Content-Type: application/json" \
-d '{
"client_msg_no": "msg_001_stream_start",
"channel_id": "group_ai_chat",
"channel_type": 2,
"from_uid": "ai_assistant",
"event": {
"type": "___TextMessageEnd",
"data": ""
}
}'
curl -X POST "http://localhost:5001/event" \
-H "Content-Type: application/json" \
-d '{
"client_msg_no": "custom_event_001",
"channel_id": "user_123",
"channel_type": 1,
"from_uid": "system",
"event": {
"type": "user_status_update",
"timestamp": 1640995200000,
"data": "{\"status\": \"online\", \"last_seen\": 1640995200000}"
}
}'
// Streaming text message example
const streamId = `stream_${Date.now()}`;
// 1. Start stream
await fetch('http://localhost:5001/event', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
client_msg_no: streamId,
channel_id: 'group_ai_chat',
channel_type: 2,
from_uid: 'ai_assistant',
event: {
type: '___TextMessageStart',
data: 'Starting AI response...'
}
})
});
// 2. Send content
await fetch('http://localhost:5001/event', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
client_msg_no: streamId,
channel_id: 'group_ai_chat',
channel_type: 2,
from_uid: 'ai_assistant',
event: {
type: '___TextMessageContent',
data: 'Hello! How can I help you today?'
}
})
});
// 3. End stream
await fetch('http://localhost:5001/event', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
client_msg_no: streamId,
channel_id: 'group_ai_chat',
channel_type: 2,
from_uid: 'ai_assistant',
event: {
type: '___TextMessageEnd',
data: ''
}
})
});
import requests
import time
# Streaming text message example
stream_id = f"stream_{int(time.time() * 1000)}"
base_url = "http://localhost:5001/event"
# 1. Start stream
requests.post(base_url, json={
"client_msg_no": stream_id,
"channel_id": "group_ai_chat",
"channel_type": 2,
"from_uid": "ai_assistant",
"event": {
"type": "___TextMessageStart",
"data": "Starting AI response..."
}
})
# 2. Send content
requests.post(base_url, json={
"client_msg_no": stream_id,
"channel_id": "group_ai_chat",
"channel_type": 2,
"from_uid": "ai_assistant",
"event": {
"type": "___TextMessageContent",
"data": "Hello! How can I help you today?"
}
})
# 3. End stream
requests.post(base_url, json={
"client_msg_no": stream_id,
"channel_id": "group_ai_chat",
"channel_type": 2,
"from_uid": "ai_assistant",
"event": {
"type": "___TextMessageEnd",
"data": ""
}
})
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"time"
)
type Event struct {
Type string `json:"type"`
Data string `json:"data"`
Timestamp int64 `json:"timestamp,omitempty"`
}
type EventRequest struct {
ClientMsgNo string `json:"client_msg_no"`
ChannelID string `json:"channel_id"`
ChannelType int `json:"channel_type"`
FromUID string `json:"from_uid"`
Event Event `json:"event"`
}
func sendEvent(req EventRequest) error {
jsonData, _ := json.Marshal(req)
resp, err := http.Post(
"http://localhost:5001/event",
"application/json",
bytes.NewBuffer(jsonData),
)
if err != nil {
return err
}
defer resp.Body.Close()
return nil
}
func main() {
streamID := fmt.Sprintf("stream_%d", time.Now().UnixMilli())
// 1. Start stream
sendEvent(EventRequest{
ClientMsgNo: streamID,
ChannelID: "group_ai_chat",
ChannelType: 2,
FromUID: "ai_assistant",
Event: Event{
Type: "___TextMessageStart",
Data: "Starting AI response...",
},
})
// 2. Send content
sendEvent(EventRequest{
ClientMsgNo: streamID,
ChannelID: "group_ai_chat",
ChannelType: 2,
FromUID: "ai_assistant",
Event: Event{
Type: "___TextMessageContent",
Data: "Hello! How can I help you today?",
},
})
// 3. End stream
sendEvent(EventRequest{
ClientMsgNo: streamID,
ChannelID: "group_ai_chat",
ChannelType: 2,
FromUID: "ai_assistant",
Event: Event{
Type: "___TextMessageEnd",
Data: "",
},
})
}
{
"status": "ok"
}
Overview
Send various types of events to channels, including streaming text messages and custom events. Supports AG-UI protocol events for real-time streaming communication.Query Parameters
Force end existing streams in the channel before starting a new one
0- Do not force end1- Force end existing streams
Request Body
Required Parameters
Client message number - must be unique and not repeated. Used to identify and track the message/stream. For streaming messages, all events in the same stream should use the same client_msg_no. UUID format is recommended.
Target channel ID where the event will be sent. For person channels, this should be the target user ID. For group channels, this should be the group ID.
Channel type
1- Person channel2- Group channel
Event object
Show event fields
Show event fields
Event type - supports AG-UI protocol events and custom eventsAG-UI Protocol Events:
___TextMessageStart- Initiates a streaming text message session___TextMessageContent- Sends content chunks during streaming___TextMessageEnd- Terminates a streaming text message session___ToolCallStart- Begins a tool/function call event___ToolCallArgs- Sends arguments for tool calls___ToolCallEnd- Ends a tool call event___ToolCallResult- Returns results from tool execution
___ is treated as a custom event typeEvent ID (optional, auto-generated for some event types)
Event timestamp (optional, Unix timestamp in milliseconds)
Event data content. The format depends on the event type:For Text Message Events:
___TextMessageStart- Initial message content or metadata___TextMessageContent- Text chunk for streaming___TextMessageEnd- Final content or completion marker
___ToolCallStart- Tool name or metadata___ToolCallArgs- JSON string with function arguments___ToolCallEnd- Completion status___ToolCallResult- JSON string with execution results
Optional Parameters
Sender user ID. If not provided or empty, defaults to the system UID. This identifies who is sending the event.
curl -X POST "http://localhost:5001/event" \
-H "Content-Type: application/json" \
-d '{
"client_msg_no": "msg_001_stream_start",
"channel_id": "group_ai_chat",
"channel_type": 2,
"from_uid": "ai_assistant",
"event": {
"type": "___TextMessageStart",
"data": "{\"type\":1,\"content\":\"Starting AI response...\"}"
}
}'
curl -X POST "http://localhost:5001/event" \
-H "Content-Type: application/json" \
-d '{
"client_msg_no": "msg_001_stream_start",
"channel_id": "group_ai_chat",
"channel_type": 2,
"from_uid": "ai_assistant",
"event": {
"type": "___TextMessageContent",
"data": "Hello! How can I help you today?"
}
}'
curl -X POST "http://localhost:5001/event" \
-H "Content-Type: application/json" \
-d '{
"client_msg_no": "msg_001_stream_start",
"channel_id": "group_ai_chat",
"channel_type": 2,
"from_uid": "ai_assistant",
"event": {
"type": "___TextMessageEnd",
"data": ""
}
}'
curl -X POST "http://localhost:5001/event" \
-H "Content-Type: application/json" \
-d '{
"client_msg_no": "custom_event_001",
"channel_id": "user_123",
"channel_type": 1,
"from_uid": "system",
"event": {
"type": "user_status_update",
"timestamp": 1640995200000,
"data": "{\"status\": \"online\", \"last_seen\": 1640995200000}"
}
}'
// Streaming text message example
const streamId = `stream_${Date.now()}`;
// 1. Start stream
await fetch('http://localhost:5001/event', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
client_msg_no: streamId,
channel_id: 'group_ai_chat',
channel_type: 2,
from_uid: 'ai_assistant',
event: {
type: '___TextMessageStart',
data: 'Starting AI response...'
}
})
});
// 2. Send content
await fetch('http://localhost:5001/event', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
client_msg_no: streamId,
channel_id: 'group_ai_chat',
channel_type: 2,
from_uid: 'ai_assistant',
event: {
type: '___TextMessageContent',
data: 'Hello! How can I help you today?'
}
})
});
// 3. End stream
await fetch('http://localhost:5001/event', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
client_msg_no: streamId,
channel_id: 'group_ai_chat',
channel_type: 2,
from_uid: 'ai_assistant',
event: {
type: '___TextMessageEnd',
data: ''
}
})
});
import requests
import time
# Streaming text message example
stream_id = f"stream_{int(time.time() * 1000)}"
base_url = "http://localhost:5001/event"
# 1. Start stream
requests.post(base_url, json={
"client_msg_no": stream_id,
"channel_id": "group_ai_chat",
"channel_type": 2,
"from_uid": "ai_assistant",
"event": {
"type": "___TextMessageStart",
"data": "Starting AI response..."
}
})
# 2. Send content
requests.post(base_url, json={
"client_msg_no": stream_id,
"channel_id": "group_ai_chat",
"channel_type": 2,
"from_uid": "ai_assistant",
"event": {
"type": "___TextMessageContent",
"data": "Hello! How can I help you today?"
}
})
# 3. End stream
requests.post(base_url, json={
"client_msg_no": stream_id,
"channel_id": "group_ai_chat",
"channel_type": 2,
"from_uid": "ai_assistant",
"event": {
"type": "___TextMessageEnd",
"data": ""
}
})
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"time"
)
type Event struct {
Type string `json:"type"`
Data string `json:"data"`
Timestamp int64 `json:"timestamp,omitempty"`
}
type EventRequest struct {
ClientMsgNo string `json:"client_msg_no"`
ChannelID string `json:"channel_id"`
ChannelType int `json:"channel_type"`
FromUID string `json:"from_uid"`
Event Event `json:"event"`
}
func sendEvent(req EventRequest) error {
jsonData, _ := json.Marshal(req)
resp, err := http.Post(
"http://localhost:5001/event",
"application/json",
bytes.NewBuffer(jsonData),
)
if err != nil {
return err
}
defer resp.Body.Close()
return nil
}
func main() {
streamID := fmt.Sprintf("stream_%d", time.Now().UnixMilli())
// 1. Start stream
sendEvent(EventRequest{
ClientMsgNo: streamID,
ChannelID: "group_ai_chat",
ChannelType: 2,
FromUID: "ai_assistant",
Event: Event{
Type: "___TextMessageStart",
Data: "Starting AI response...",
},
})
// 2. Send content
sendEvent(EventRequest{
ClientMsgNo: streamID,
ChannelID: "group_ai_chat",
ChannelType: 2,
FromUID: "ai_assistant",
Event: Event{
Type: "___TextMessageContent",
Data: "Hello! How can I help you today?",
},
})
// 3. End stream
sendEvent(EventRequest{
ClientMsgNo: streamID,
ChannelID: "group_ai_chat",
ChannelType: 2,
FromUID: "ai_assistant",
Event: Event{
Type: "___TextMessageEnd",
Data: "",
},
})
}
{
"status": "ok"
}
Response Fields
Operation status, returns
"ok" on successStatus Codes
| Status Code | Description |
|---|---|
| 200 | Event sent successfully |
| 400 | Bad request - invalid parameters or event data |
| 500 | Internal server error |
Streaming Message Flow
Streaming Message Process
- Start Stream: Send
___TextMessageStartevent to initiate a stream - Send Content: Send multiple
___TextMessageContentevents with message chunks - End Stream: Send
___TextMessageEndevent to close the stream
Important Notes
- The same
client_msg_nomust be used for all events in a streaming session - Only one stream can be active per channel unless
force=1is used - For person channels, the system automatically handles fake channel ID generation
- Events are automatically routed to the appropriate cluster node
Event Types
AG-UI Protocol Events
AG-UI protocol events enable real-time streaming communication for AI applications:| Event Type | Purpose | Data Format |
|---|---|---|
___TextMessageStart | Initiates a streaming text message session | Initial content or metadata |
___TextMessageContent | Sends content chunks during streaming | Text chunk content |
___TextMessageEnd | Terminates a streaming text message session | Completion marker |
___ToolCallStart | Begins a tool/function call event | Tool name or metadata |
___ToolCallArgs | Sends arguments for tool calls | JSON formatted arguments |
___ToolCallEnd | Ends a tool call event | Completion status |
___ToolCallResult | Returns results from tool execution | JSON formatted results |
Custom Events
Any event type not starting with___ is treated as a custom event, useful for:
- User status updates
- System notifications
- Business logic events
- Application-specific interactions
Use Cases
AI Chatbot
# Simulate AI typing effect
curl -X POST "/event" -d '{
"client_msg_no": "ai_response_001",
"channel_id": "user_123",
"channel_type": 1,
"from_uid": "ai_bot",
"event": {
"type": "___TextMessageStart",
"data": "Thinking..."
}
}'
# Gradually send response content
curl -X POST "/event" -d '{
"client_msg_no": "ai_response_001",
"channel_id": "user_123",
"channel_type": 1,
"from_uid": "ai_bot",
"event": {
"type": "___TextMessageContent",
"data": "Based on your question, I recommend..."
}
}'
Real-time Collaboration
# Document editing status
curl -X POST "/event" -d '{
"client_msg_no": "doc_edit_001",
"channel_id": "doc_room_456",
"channel_type": 2,
"from_uid": "user_789",
"event": {
"type": "document_editing",
"data": "{\"action\": \"start_edit\", \"section\": \"paragraph_1\"}"
}
}'
System Notifications
# User online notification
curl -X POST "/event" -d '{
"client_msg_no": "status_update_001",
"channel_id": "group_general",
"channel_type": 2,
"from_uid": "system",
"event": {
"type": "user_online",
"timestamp": 1640995200000,
"data": "{\"user_id\": \"user_123\", \"status\": \"online\"}"
}
}'
Best Practices
- Unique Identification: Use UUID format for
client_msg_noto ensure uniqueness - Stream Management: Close unused streams promptly to avoid resource waste
- Error Handling: Handle stream conflicts and send failures
- Permission Verification: Ensure sender has channel send permissions
- Data Format: Use JSON format strings for complex data
- Performance Optimization: Control streaming message send frequency reasonably
Error Handling
Common Errors
| Error | Cause | Solution |
|---|---|---|
| Event type cannot be empty | No event.type provided | Ensure valid event type is provided |
| Stream already running in channel | Trying to start new stream when one is active | Use force=1 or wait for existing stream to end |
| Stream does not exist | Trying to send content to non-existent stream | Check if stream was created correctly |
| Stream is already closed | Sending content to closed stream | Start a new stream |
Retry Mechanism
For temporary errors, implement exponential backoff retry mechanism:async function sendEventWithRetry(eventData, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fetch('/event', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(eventData)
});
if (response.ok) return await response.json();
if (response.status >= 400 && response.status < 500) {
// Client error, don't retry
throw new Error(`Client error: ${response.status}`);
}
} catch (error) {
if (i === maxRetries - 1) throw error;
await new Promise(resolve => setTimeout(resolve, Math.pow(2, i) * 1000));
}
}
}
⌘I

