跳到主要内容

WebSocket API

WebSocket real-time communication endpoints

Overview​

Viben Gateway provides multiple WebSocket endpoints for real-time communication:

  • General WebSocket (/ws)
  • Agent Execution WebSocket (/ws/agent/run)
  • Group Chat WebSocket (/api/group-chats/:id/sessions/:sid/ws)
  • Terminal WebSocket (/terminal/ws)

Endpoint List​

PathDescription
/wsGeneral WebSocket, event subscription
/ws/agent/runAgent execution, supports interactive Q&A
/api/group-chats/:id/sessions/:sid/wsGroup chat session real-time communication
/terminal/wsTerminal PTY session

Agent Execution WebSocket​

GET /ws/agent/run​

Agent execution WebSocket connection, supports bidirectional communication and interactive features (such as AskUserQuestion, EnterPlanMode).

Query Parameters:

ParameterTypeRequiredDescription
cwdstringNoWorking directory
agent_config_pathstringNoAgent config file path (e.g., /path/to/agents/myagent/AGENTS.md)
session_idstringNoSession ID (for persistence)
task_idstringNoTask ID (for persistence)

Note: This endpoint also accepts the camelCase aliases agentConfigPath, sessionId, and taskId for backward compatibility, but snake_case is the documented gateway convention. Client Messages:

// Start execution
{
"type": "start",
"prompt": "Please help me create a React component",
"agentConfig": { // Optional, if agentConfigPath not provided
"name": "my-agent",
"model": "claude-sonnet-4-20250514",
"systemPrompt": "You are a helpful assistant."
}
}

// Answer question (AskUserQuestion)
{
"type": "answer",
"questionId": "tool_use_123",
"answers": {
"question_0": "Option A"
}
}

// Approve plan
{
"type": "approve",
"planId": "plan_123"
}

// Reject plan
{
"type": "reject",
"planId": "plan_123"
}

// Cancel execution
{
"type": "cancel"
}

Server Messages:

Message format is compatible with SSE endpoint /api/agent/run:

// Session created
{
"type": "session",
"sessionId": "abc-123-def",
"traceId": "trace-456"
}

// Text content (streaming)
{
"type": "text",
"content": "I'll help you create..."
}

// Tool call
{
"type": "tool_use",
"id": "tool_use_123",
"name": "Write",
"input": {
"file_path": "/path/to/file.tsx",
"content": "..."
}
}

// Tool result
{
"type": "tool_result",
"toolUseId": "tool_use_123",
"output": "File created successfully",
"isError": false
}

// Interactive question (AskUserQuestion)
{
"type": "question",
"id": "tool_use_456",
"questions": [
{
"header": "Select Configuration",
"question": "Please select your preferred configuration method:",
"options": [
{ "label": "Default Config", "description": "Use recommended settings" },
{ "label": "Custom Config", "description": "Manually set all options" }
],
"multiSelect": false
}
]
}

// Plan (EnterPlanMode)
{
"type": "plan",
"plan": {
"id": "plan_789",
"goal": "Create React component",
"steps": [
{ "id": "1", "description": "Create component file", "status": "pending" },
{ "id": "2", "description": "Add styles", "status": "pending" }
],
"notes": "This is a simple component creation plan"
}
}

// Execution result
{
"type": "result",
"subtype": "success",
"cost": 0.05,
"duration": 5000
}

// Error
{
"type": "error",
"message": "Execution failed:..."
}

// Done
{
"type": "done"
}

Features:

  • Interactive Q&A: Agent can ask users questions via question message, users reply via answer message
  • Plan approval: Agent can send plans, users can approve or reject
  • Auto-reconnect: Client can reconnect after disconnection and resume session
  • SSE-compatible format: Easy to switch between WebSocket and SSE

Example (JavaScript):

const ws = new WebSocket('ws://localhost:18790/ws/agent/run?cwd=/my/project');

ws.onopen = () => {
// Send start message
ws.send(JSON.stringify({
type: 'start',
prompt: 'Please help me create a React component'
}));
};

ws.onmessage = (event) => {
const msg = JSON.parse(event.data);

switch (msg.type) {
case 'text':
console.log('Agent:', msg.content);
break;
case 'question':
// Display question to user
console.log('Question:', msg.questions[0].question);
// Send answer after user selection
ws.send(JSON.stringify({
type: 'answer',
questionId: msg.id,
answers: { 'question_0': 'Option A' }
}));
break;
case 'done':
console.log('Completed');
break;
}
};

General WebSocket​

GET /ws​

General WebSocket connection for subscribing to system events.

Event Channels:

ChannelDescription
cronCron job events
channelsChannel events
groupGroup chat events
tasksTask events
sessionsSession events
agentsAgent events
gatewayGateway events
queueTask queue events

Client Messages:

// Subscribe to events
{
"type": "subscribe",
"channels": ["cron", "agents"]
}

// Unsubscribe from events
{
"type": "unsubscribe",
"channels": ["cron"]
}

Server Messages:

{
"channel": "agents",
"type": "AgentSpawned",
"data": {
"agent_id": "CLAUDE_CODE",
"session_id": "abc123",
"workdir": "/path/to/project"
},
"timestamp": "2024-01-16T10:00:00Z"
}

Group Chat WebSocket​

GET /api/group-chats/:id/sessions/:sid/ws​

Group chat session WebSocket connection.

Query Parameters:

ParameterTypeRequiredDescription
workspace_pathstringNoWorkspace path
member_typestringNoMember type
member_idstringNoMember ID

Client Messages:

// Send message
{
"type": "send_message",
"data": {
"content": "Hello everyone"
}
}

// Switch view
{
"type": "switch_view",
"data": {
"view": "agent",
"agent_id": "CLAUDE_CODE"
}
}

// Typing indicator
{
"type": "typing",
"data": {
"is_typing": true
}
}

Server Messages:

// New message
{
"type": "message",
"data": {
"id": "msg-123",
"sender": {
"type": "agent",
"agent_id": "CLAUDE_CODE"
},
"content": "I'll help with that..."
}
}

// Agent thinking
{
"type": "agent_thinking",
"data": {
"agent_id": "CLAUDE_CODE",
"status": "thinking"
}
}

// Agent response
{
"type": "agent_response",
"data": {
"agent_id": "CLAUDE_CODE",
"status": "completed",
"message_id": "msg-456"
}
}

// Typing indicator
{
"type": "typing_indicator",
"data": {
"member_id": "user-1",
"is_typing": true
}
}

// Error
{
"type": "error",
"data": {
"code": "AGENT_ERROR",
"message": "Agent failed to respond"
}
}

Terminal WebSocket​

GET /terminal/ws​

Terminal PTY session WebSocket connection.

Query Parameters:

ParameterTypeRequiredDefaultDescription
cwdstringNocwdWorking directory
colsintNo80Terminal columns
rowsintNo24Terminal rows

Data Encoding: Base64

Client Messages:

// Input data (Base64 encoded)
{
"type": "input",
"data": "bHMgLWxhCg==" // "ls -la\n"
}

// Resize
{
"type": "resize",
"data": {
"cols": 120,
"rows": 40
}
}

Server Messages:

// Output data (Base64 encoded)
{
"type": "output",
"data": "dG90YWwgMTI4Cg=="
}

// Terminal closed
{
"type": "exit",
"data": {
"code": 0
}
}

Example (JavaScript):

const ws = new WebSocket('ws://localhost:18790/terminal/ws?cols=80&rows=24');

ws.onopen = () => {
// Send command
const input = btoa('ls -la\n');
ws.send(JSON.stringify({ type: 'input', data: input }));
};

ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
if (msg.type === 'output') {
const output = atob(msg.data);
console.log(output);
}
};

Event Types Summary​

Task Events​

TypeDescription
TaskCreatedTask created
TaskUpdatedTask updated
TaskDeletedTask deleted
TaskStatusChangedTask status changed

Agent Events​

TypeDescription
AgentSpawnedAgent started
AgentCompletedAgent completed
AgentErrorAgent error

Group Chat Events​

TypeDescription
GroupChatMessageNew message
GroupChatAgentThinkingAgent thinking
GroupChatAgentResponseAgent response

Cron Job Events​

TypeDescription
CronJobTriggeredJob triggered
CronJobCompletedJob completed
CronJobFailedJob failed

Connection Management​

Heartbeat​

WebSocket connections use ping/pong mechanism to stay alive:

  • Server sends ping every 30 seconds
  • Client should respond with pong within 10 seconds
  • Connection will be closed if no response within timeout

Reconnection​

It is recommended that clients implement automatic reconnection logic:

function connect() {
const ws = new WebSocket('ws://localhost:18790/ws');

ws.onclose = () => {
setTimeout(connect, 3000); // Reconnect after 3 seconds
};

ws.onerror = () => {
ws.close();
};
}