Chuyển tới nội dung chính

Các Lệnh Client Gửi Lên Server

Tổng Hợp Lệnh​

typeMô tả
chatBắt đầu lượt hội thoại mới
subscribeĐăng ký nhận events của session
stopDừng agent đang chạy
push_messageXếp hàng message khi agent đang bận
approvalPhê duyệt tool call hoặc trả lời câu hỏi
ping / pongKeep-alive

chat — Bắt Đầu Lượt Hội Thoại​

{
"type": "chat",
"message": "Phân tích cổ phiếu VNM",
"session_id": "uuid-session-id",
"model": "claude-sonnet-4-6",
"agent_id": "financial_agent",
"content_urls": [
"https://example.com/bao-cao.pdf"
],
"agent_config": {
"display_mode": "agent"
}
}
FieldBắt buộcMô tả
messageCóNội dung tin nhắn người dùng
session_idKhôngBỏ trống để tạo session mới
modelKhôngOverride model (mặc định theo cấu hình server)
agent_idKhôngOverride agent
content_urlsKhôngDanh sách URL file/ảnh đính kèm
agent_config.display_modeKhông"agent" (mặc định) hoặc "chat"

display_mode: "agent" — hiển thị thinking, tool calls, toàn bộ quá trình suy luận.

display_mode: "chat" — chỉ trả về text answer, không có thinking hay tool call events.

Session Mới​

Khi không có session_id, server tạo session mới và trả về trong subscribed.session_id. Client phải lưu lại ID này để dùng cho các lượt tiếp theo.

Response Sau chat​

{
"type": "subscribed",
"session_id": "abc-123",
"status": "running"
}

Sau đó server bắt đầu stream toàn bộ events của lượt (xem Event Stream).

Khi Agent Đang Bận​

Nếu session đã có task đang chạy, message được tự động xếp hàng:

{
"type": "message_queued",
"session_id": "abc-123"
}

subscribe — Đăng Ký Nhận Events​

Dùng khi reconnect hoặc muốn nhận lại events từ một điểm cụ thể.

{
"type": "subscribe",
"session_id": "abc-123",
"last_event_id": "01HXYZ..."
}
FieldBắt buộcMô tả
session_idCóSession cần subscribe
last_event_idKhôngReplay từ event ID này. Bỏ trống để nhận toàn bộ

Response​

{
"type": "subscribed",
"session_id": "abc-123",
"status": "running"
}

hoặc:

{
"type": "subscribed",
"session_id": "abc-123",
"status": "completed"
}
  • status: "running" → server replay events còn thiếu + tiếp tục stream live
  • status: "completed" → server replay events còn thiếu rồi dừng

Lỗi Session Không Tồn Tại​

{
"type": "error",
"code": "SESSION_NOT_FOUND",
"message": "Session not found or no active stream"
}

stop — Dừng Agent​

{
"type": "stop",
"session_id": "abc-123"
}

Server đặt stop signal. Agent dừng ở lần kiểm tra tiếp theo (thường < 1 giây).

Sau khi dừng, server sẽ emit:

  1. Block terminal_user_stopped
  2. message_delta
  3. message_stop

Không có ACK trực tiếp — message_stop là xác nhận cuối cùng.

Nếu không có task đang chạy:

{
"type": "error",
"code": "SESSION_NOT_RUNNING",
"message": "No running task for this session"
}

push_message — Xếp Hàng Message​

{
"type": "push_message",
"session_id": "abc-123",
"message": "Cũng phân tích thêm cổ phiếu HPG"
}

Message được xử lý ngay sau khi lượt hiện tại hoàn thành.

{
"type": "message_queued",
"session_id": "abc-123"
}

Bảng Mã Lỗi​

codeKhi nào
INVALID_JSONMessage không phải JSON hợp lệ
UNKNOWN_TYPETrường type không xác định
EMPTY_MESSAGEchat không có message
MISSING_SESSION_IDsubscribe không có session_id
SESSION_NOT_FOUNDSession không tồn tại hoặc đã hết TTL
SESSION_NOT_RUNNINGstop / push_message khi không có task
TASK_START_FAILEDLỗi nội bộ khi khởi động task

Ví Dụ: React.js​

function ChatInput({ sessionId, ws, onSessionCreated }) {
const [message, setMessage] = useState('')

const sendMessage = () => {
if (!message.trim()) return

ws.send(JSON.stringify({
type: 'chat',
message: message.trim(),
session_id: sessionId || undefined,
agent_config: { display_mode: 'agent' },
}))
setMessage('')
}

const stopAgent = () => {
if (!sessionId) return
ws.send(JSON.stringify({ type: 'stop', session_id: sessionId }))
}

return (
<div>
<input value={message} onChange={e => setMessage(e.target.value)} />
<button onClick={sendMessage}>Gửi</button>
<button onClick={stopAgent}>Dừng</button>
</div>
)
}

Ví Dụ: Flutter (Dart)​

class ChatService {
final AgentWebSocket _ws;
String? _sessionId;

ChatService(this._ws);

void sendMessage(String message) {
final payload = {
'type': 'chat',
'message': message,
if (_sessionId != null) 'session_id': _sessionId,
'agent_config': {'display_mode': 'agent'},
};
_ws.send(payload);
}

void stop() {
if (_sessionId == null) return;
_ws.send({'type': 'stop', 'session_id': _sessionId});
}

void pushMessage(String message) {
if (_sessionId == null) return;
_ws.send({
'type': 'push_message',
'session_id': _sessionId,
'message': message,
});
}

void handleSubscribed(Map<String, dynamic> msg) {
_sessionId = msg['session_id'] as String;
// Lưu vào local storage để dùng khi reconnect
SharedPreferences.getInstance()
.then((prefs) => prefs.setString('last_session_id', _sessionId!));
}
}