# WSCLI API Reference This document covers the complete API surface of `@agent-smith/wscli`, including the WebSocket connection setup, message protocol, streaming responses, and error handling. ## WebSocket Connection Setup ### `useWsServer` Factory Function The primary entry point is the `useWsServer` factory function, which creates a WebSocket client connected to an Agent Smith server. ```typescript function useWsServer(params: ServerParams): WsServerHandle; ``` **Parameters:** | Parameter | Type | Description | |-----------|------|-------------| | `params` | `ServerParams` | Configuration and callback handlers | **Return value:** An object with methods to execute features (`executeAgent`, `executeWorkflow`, `cancel`) and exposed callback references. ### ServerParams Interface ```typescript interface ServerParams extends AllCallbacks { url?: string; // WebSocket URL (default: ws://localhost:5184/ws) isVerbose?: boolean; // Enable verbose logging defaultInferenceParams?: InferenceParams; // Default inference parameters onConfirmToolUsage?: (tool: ToolCallSpec) => Promise; // Tool confirmation handler } ``` `ServerParams` extends `AllCallbacks`, which combines `InferenceCallbacks` and `AgentCallbacks`. All callbacks are optional. **Default URL:** If no `url` is provided, the client connects to `ws://localhost:5184/ws`. ## Message Protocol ### WsClientMsg Structure Messages sent from the client to the server follow this structure: ```typescript interface WsClientMsg { command: string; // Command name (e.g., agent name, workflow name) type: 'command' | 'system'; // Message category feature?: FeatureType; // Optional: 'agent', 'action', 'workflow', 'adaptater', 'cmd', 'skill' payload?: any; // Command-specific payload options?: Record; // Additional execution options } ``` **Message Types:** | Type | Purpose | |------|---------| | `'command'` | Execute a feature (agent, workflow, action, etc.) — includes `feature`, `payload`, and `options` fields | | `'system'` | Control messages such as `stop` (cancel) or `confirmtool` (tool confirmation) | **FeatureType Values:** `'agent' | 'action' | 'workflow' | 'adaptater' | 'cmd' | 'skill'` ### WsRawServerMsg Structure Messages received from the server: ```typescript interface WsRawServerMsg { type: WsServerMsgType; // Message type identifier from: string; // Source identifier msg: string; // Raw JSON string payload } ``` ## Sending Commands to Server ### executeAgent Execute an agent by name with a prompt: ```typescript function executeAgent(name: string, payload: any, options?: Record): void; ``` **Example:** ```typescript import { useWsServer } from "@agent-smith/wscli"; const ws = useWsServer({ onToken: (token, from) => process.stdout.write(token), }); ws.executeAgent("my-agent", { prompt: "Analyze this data" }); ``` ### executeWorkflow Execute a workflow by name with a payload: ```typescript function executeWorkflow(name: string, payload: any, options?: Record): void; ``` **Example:** ```typescript ws.executeWorkflow("data-pipeline", { input: "file.csv" }); ``` ### cancel Send a system stop command to cancel a running inference: ```typescript function cancel(): Promise; ``` **Example:** ```typescript await ws.cancel(); ``` ### Internal Message Construction The client internally constructs `WsClientMsg` objects: - **Feature execution** (`executeAgent`, `executeWorkflow`): Creates a message with `type: "command"`, the feature name as `command`, the appropriate `feature` type (`"agent"` or `"workflow"`), and the provided `payload` and `options`. - **Cancel**: Creates a system message with `type: "system"`, `command: "stop"`. ## Receiving Streaming Responses The server streams various message types over the WebSocket. Each message type triggers a corresponding callback from `ServerParams`. ### WsServerMsgType Values | Type | Callback | Description | |------|----------|-------------| | `'error'` | `onError(err, from)` | Error message from the server | | `'startemit'` | `onStartEmit(data, from)` | Inference started — includes `PromptProcessingInProgressStats` | | `'token'` | `onToken(token, from)` | Generated output token (string) | | `'thinkingtoken'` | `onThinkingToken(token, from)` | Thinking/reasoning token (string) | | `'turnstart'` | `onTurnStart(from)` | New conversation turn began | | `'turnend'` | `onTurnEnd(history, from)` | Turn completed — includes `HistoryTurn` | | `'assistant'` | `onAssistant(text, from)` | Assistant text output (string) | | `'think'` | `onThink(text, from)` | Model thinking content (string) | | `'thinkingstart'` | `onStartThinking(from)` | Thinking block started | | `'thinkingend'` | `onEndThinking(from)` | Thinking block ended | | `'toolcallinprogress'` | `onToolCallInProgress(tc, from)` | Tool execution in progress — array of `ToolCallSpec` | | `'promptprocessingprogress'` | `onPromptProcessingProgress(progress, from)` | Prompt processing stats — `PromptProcessingInProgressStats` | | `'toolcalltoken'` | `onToolCallToken(token, from)` | Token from tool call output (string) | | `'toolsturnstart'` | `onToolsTurnStart(tc, from)` | Tools turn started — array of `ToolCallSpec` | | `'toolsturnend'` | `onToolsTurnEnd(tt, from)` | Tools turn ended — array of `ToolTurn` | | `'toolcall'` | `onToolCall(tc, type, from)` | Tool call initiated — payload contains `{ tc, type, from }` | | `'toolcallend'` | `onToolCallEnd(tc, content, type, from)` | Tool call completed — splits on `<|xtool_call_id|>` to extract content | | `'toolcallconfirm'` | Triggers `onConfirmToolUsage` | Awaiting tool confirmation — sends back `{ confirm: boolean, id }` via system message | | `'finalresult'` | `onTurnEnd(history, from)` | Final inference result — includes `HistoryTurn` (also triggers `onTurnEnd`) | | `'endemit'` | `onEndEmit(result, from)` | Inference complete — includes `InferenceResult` | ### Streaming Example ```typescript import { useWsServer } from "@agent-smith/wscli"; const ws = useWsServer({ onToken: (token, from) => { process.stdout.write(token); // Stream tokens to stdout }, onThinkingToken: (token, from) => { console.log(`[thinking] ${token}`); }, onToolCall: (tc, type, from) => { console.log(`Tool call: ${tc.name}(${JSON.stringify(tc.arguments)})`); }, onTurnStart: (from) => { console.log(`\n=== New turn from ${from} ===`); }, onTurnEnd: (history, from) => { console.log(`\n=== Turn ended from ${from} ===`); }, onError: (err, from) => { console.error(`[${from}] Error: ${err}`); }, }); ws.executeAgent("my-agent", { prompt: "Process the data" }); ``` ### Tool Confirmation Flow When the server sends a `toolcallconfirm` message, the `onConfirmToolUsage` callback is invoked with a `ToolCallSpec`. The client automatically sends back a system message (`command: "confirmtool"`) with the user's confirmation result: ```typescript const ws = useWsServer({ onConfirmToolUsage: async (tool) => { const confirmed = await askUser(`Allow tool "${tool.name}"?`); return confirmed; // Client sends { command: "confirmtool", payload: { confirm, id } } }, }); ``` ## Error Handling and Reconnection ### Automatic Reconnection The client uses `ReconnectingWebSocket` which handles reconnection automatically. When the connection drops, it will retry with increasing intervals until successful. ### Message Send Retry If a message is sent while the WebSocket is not in `OPEN` state, the internal `_sendMsg` function retries with exponential backoff (1s → 1.5s → 2s → ... → 5s max): ```typescript // Internal retry logic if (ws.readyState !== WebSocket.OPEN) { console.warn('Cannot send message - not connected'); setTimeout(() => _sendMsg(m, t + 500), Math.min(t + 500, 5000)); } ``` ### Error Callbacks Errors from the server are delivered via the `onError(err, from)` callback. If no handler is provided, errors are logged to `console.error` with the source identifier. Connection-level errors (network failures) are logged to `console.error` by the underlying `ReconnectingWebSocket`. ## API Reference ### Exported Functions | Function | Signature | Description | |----------|-----------|-------------| | `useWsServer` | `(params: ServerParams) => WsServerHandle` | Factory function creating a WebSocket client connection | | `useClientFeatures` | `(params?: ServerParams) => ClientFeaturesService` | Higher-level service wrapping `useWsServer` with reactive state, variable management, and REST API integration | ### WsServerHandle Return Type ```typescript interface WsServerHandle { executeWorkflow: (name: string, payload: any, options?: Record) => void; executeAgent: (name: string, payload: any, options?: Record) => void; cancel: () => Promise; onToken: ((t: string, from: string) => void) | undefined; onToolCall: ((tc: ToolCallSpec, type: string, from: string) => void) | undefined; onToolCallEnd: ((tc: ToolCallSpec, tr: any, type: string, from: string) => void) | undefined; onError: ((err: any, from: string) => void) | undefined; onConfirmToolUsage: ((tool: ToolCallSpec) => Promise) | undefined; } ``` ### ClientFeaturesService Interface `useClientFeatures` returns a service with reactive state and REST API integration: ```typescript interface ClientFeaturesService { isReady: Ref; // Whether agent spec has been loaded agentSpec: Ref; // Loaded agent specification variables: Reactive; // Agent variables (required/optional) mcp: Reactive<{ servers: Record }>; // MCP server configs load: (name: string) => Promise; // Load agent spec and variables loadWorkflow: (name: string) => Promise>; executeAgent: (prompt: string, opts?: ClientFeaturesOptions) => Promise; executeAgentSync: (prompt: string, opts?: ClientFeaturesOptions) => Promise; executeWorkflow: (name: string, payload: any, options?: ClientFeaturesOptions) => Promise; executeWorkflowSync: (name: string, payload: any, options?: ClientFeaturesOptions) => Promise; cancel: () => Promise; loadModels: (backend: string) => Promise>; loadSamplingPresets: () => Promise>; loadAgentSettings: () => Promise>; loadBackends: () => Promise>; setBackend: (name: string) => Promise; getTools: (tools: Array) => Promise>; checkState: () => Promise<{ found: boolean, config: ConfigFile }>; loadWorkspaces: () => Promise>; loadSettings: () => Promise>; } ``` ### ClientFeaturesOptions Interface ```typescript interface ClientFeaturesOptions extends AgentInferenceOptions { backend?: string; // Override backend variables?: Record; // Override agent variables nohistory?: boolean; // Skip history recording } ``` ← Back: Get Started