Protocol API Reference¶
Overview¶
The NebulaFlow protocol defines the message contract between the VS Code extension (host) and the webview (React UI). All messages are typed for type safety and follow a strict schema. The protocol is defined in workflow/Core/Contracts/Protocol.ts.
Message Flow¶
Direction¶
- Webview → Extension: Commands (requests for actions)
- Extension → Webview: Events (notifications and data)
Message Types¶
Commands (Webview → Extension)¶
Commands are requests from the webview to the extension to perform actions.
Workflow Management¶
| Command | Description | Payload |
|---|---|---|
save_workflow |
Save workflow to disk | { nodes, edges, state } |
load_workflow |
Load workflow from disk | - |
load_last_workflow |
Load last opened workflow | - |
execute_workflow |
Start workflow execution | { nodes, edges, state, resume } |
abort_workflow |
Stop all workflow execution | - |
pause_workflow |
Pause running workflow | - |
clear_workflow |
Clear current workflow | - |
reset_results |
Clear execution results | - |
Node Operations¶
| Command | Description | Payload |
|---|---|---|
execute_node |
Execute single node | { node, inputs, runId, variables } |
llm_node_chat |
Chat with LLM node | { node, threadID, message, mode } |
node_approved |
Approve node execution | { nodeId, modifiedCommand } |
node_rejected |
Reject node execution | { nodeId, reason } |
calculate_tokens |
Calculate token count | { text, nodeId } |
Custom Nodes¶
| Command | Description | Payload |
|---|---|---|
save_customNode |
Save custom node definition | { node: WorkflowNodeDTO } |
delete_customNode |
Delete custom node | { nodeId: string } |
rename_customNode |
Rename custom node | { oldNodeTitle, newNodeTitle } |
get_custom_nodes |
Request custom nodes | - |
Subflows¶
| Command | Description | Payload |
|---|---|---|
create_subflow |
Create new subflow | { subflow: SubflowDefinitionDTO } |
get_subflow |
Get subflow by ID | { id: string } |
get_subflows |
List all subflows | - |
duplicate_subflow |
Duplicate subflow | { id, nodeId } |
Storage & Configuration¶
| Command | Description | Payload |
|---|---|---|
get_storage_scope |
Request storage scope info | - |
toggle_storage_scope |
Toggle storage scope | - |
get_models |
Request available LLM models | - |
Clipboard¶
| Command | Description | Payload |
|---|---|---|
copy_selection |
Copy selected nodes/edges | { nodes, edges } |
paste_selection |
Paste clipboard content | - |
External¶
| Command | Description | Payload |
|---|---|---|
open_external_link |
Open URL in external browser | { url: string } |
Events (Extension → Webview)¶
Events are notifications from the extension to the webview, typically containing data or status updates.
Workflow State¶
| Event | Description | Payload |
|---|---|---|
workflow_loaded |
Workflow data loaded from disk | { nodes, edges, state } |
workflow_saved |
Workflow successfully saved | { path? } |
workflow_save_failed |
Workflow save failed | { error? } |
Execution Status¶
| Event | Description | Payload |
|---|---|---|
execution_started |
Workflow execution started | - |
execution_completed |
Workflow execution completed | { stoppedAtNodeId? } |
execution_paused |
Workflow execution paused | { stoppedAtNodeId? } |
node_execution_status |
Node execution status update | { nodeId, status, result, command } |
Content Streaming¶
| Event | Description | Payload |
|---|---|---|
node_assistant_content |
LLM assistant content stream | { nodeId, threadID?, content, mode? } |
node_output_chunk |
CLI output stream | { nodeId, chunk, stream } |
token_count |
Token count result | { count, nodeId } |
Models & Configuration¶
| Event | Description | Payload |
|---|---|---|
models_loaded |
Available LLM models loaded | { models: Model[] } |
provide_custom_nodes |
Custom nodes loaded | { nodes: WorkflowNodeDTO[] } |
storage_scope |
Storage scope information | { scope, basePath? } |
Subflow Events¶
| Event | Description | Payload |
|---|---|---|
subflow_saved |
Subflow saved successfully | { id } |
provide_subflow |
Subflow data provided | { subflow: SubflowDefinitionDTO } |
provide_subflows |
List of subflows provided | { id, title, version }[] |
subflow_copied |
Subflow duplicated | { nodeId, oldId, newId } |
Subflow-Scoped Events¶
When viewing a subflow, these events are forwarded from the inner workflow:
| Event | Description | Payload |
|---|---|---|
subflow_node_execution_status |
Node execution status in subflow | { subflowId, payload } |
subflow_node_assistant_content |
Assistant content in subflow | { subflowId, nodeId, threadID?, content, mode? } |
Clipboard Events¶
| Event | Description | Payload |
|---|---|---|
clipboard_paste |
Clipboard paste result | { nodes, edges } |
Data Types¶
Basic Types¶
Model¶
Represents an available LLM model.
Node & Edge Types¶
WorkflowNodeDTO¶
interface WorkflowNodeDTO {
id: string
type: string
data: Record<string, unknown>
position: { x: number; y: number }
selected?: boolean
}
Transport-friendly workflow node DTO (neutral shape).
Fields:
- id: Unique node identifier
- type: Node type (e.g., 'llm', 'cli', 'condition')
- data: Node-specific configuration data
- position: Visual position in the workflow editor
- selected: Whether the node is currently selected
EdgeDTO¶
interface EdgeDTO {
id: string
source: string
target: string
sourceHandle?: string
targetHandle?: string
}
Transport-friendly edge DTO.
Fields:
- id: Unique edge identifier
- source: Source node ID
- target: Target node ID
- sourceHandle: Source handle identifier (optional)
- targetHandle: Target handle identifier (optional)
Execution Types¶
NodeExecutionPayload¶
interface NodeExecutionPayload {
nodeId: string
status: 'running' | 'completed' | 'error' | 'interrupted' | 'pending_approval'
result?: string
multi?: string[]
command?: string
}
Execution status payload for node updates.
Fields:
- nodeId: Node identifier
- status: Current execution status
- result: Execution result (for completed/error nodes)
- multi: Multi-output results (for nodes like Subflow)
- command: CLI command (for CLI nodes)
NodeSavedState¶
interface NodeSavedState {
status: 'completed' | 'error' | 'interrupted'
output: string
error?: string
tokenCount?: number
}
Saved state for a single node after execution.
Fields:
- status: Final execution status
- output: Node output
- error: Error message (if failed)
- tokenCount: Token count (for LLM nodes)
Workflow State¶
WorkflowStateDTO¶
interface WorkflowStateDTO {
nodeResults: Record<string, NodeSavedState>
ifElseDecisions?: Record<string, 'true' | 'false'>
nodeAssistantContent?: Record<string, AssistantContentItem[]>
nodeThreadIDs?: Record<string, string>
}
Workflow state envelope persisted across save/load.
Fields:
- nodeResults: Saved state for each executed node
- ifElseDecisions: Branch decisions for If/Else nodes
- nodeAssistantContent: Persisted assistant timelines per node (for LLM chat history)
- nodeThreadIDs: Thread identifiers per node (for LLM chat continuity)
WorkflowPayloadDTO¶
interface WorkflowPayloadDTO {
nodes?: WorkflowNodeDTO[]
edges?: EdgeDTO[]
state?: WorkflowStateDTO
resume?: ResumeDTO
}
Common workflow payload for commands/events.
Fields:
- nodes: Workflow nodes
- edges: Workflow edges
- state: Workflow execution state
- resume: Resume metadata for paused workflows
Assistant Content¶
AssistantContentItem¶
type AssistantContentItem =
| { type: 'text'; text: string }
| { type: 'user_message'; text: string }
| { type: 'thinking'; thinking: string }
| { type: 'tool_use'; id: string; name: string; inputJSON?: string }
| { type: 'tool_result'; toolUseID: string; resultJSON?: string }
| { type: 'server_tool_use'; name: string; inputJSON?: string }
| { type: 'server_web_search_result'; query?: string; resultJSON?: string }
Assistant/user/tool content blocks streamed during LLM node execution.
Types:
- text: Plain text content from the assistant
- user_message: User message in the conversation
- thinking: Assistant's internal reasoning
- tool_use: Tool/function call request
- tool_result: Tool/function call result
- server_tool_use: Server-side tool execution
- server_web_search_result: Web search results
Subflow Types¶
SubflowPortDTO¶
Input/output port for subflows.
Fields:
- id: Port identifier
- name: Port name
- index: Port order/index
SubflowGraphDTO¶
Subflow graph definition.
Fields:
- nodes: Nodes in the subflow
- edges: Edges in the subflow
SubflowDefinitionDTO¶
interface SubflowDefinitionDTO {
id: string
title: string
version: string
inputs: SubflowPortDTO[]
outputs: SubflowPortDTO[]
graph: SubflowGraphDTO
}
Complete subflow definition.
Fields:
- id: Subflow identifier
- title: Subflow display name
- version: Subflow version
- inputs: Input ports
- outputs: Output ports
- graph: Subflow graph structure
Resume Types¶
ResumeDTO¶
interface ResumeDTO {
fromNodeId?: string
seeds?: {
outputs?: Record<string, string>
decisions?: Record<string, 'true' | 'false'>
variables?: Record<string, string>
}
}
Resume metadata for paused/interrupted workflows.
Fields:
- fromNodeId: Node to resume from
- seeds: Data to inject when resuming
- outputs: Node output values
- decisions: Branch decisions
- variables: Variable values
Message Envelope¶
BaseWorkflowMessage¶
Base interface for all workflow messages. Every message must have a type field.
Protocol Implementation Notes¶
Type Safety¶
All messages are typed using TypeScript interfaces. This ensures:
- Compile-time validation: Type errors are caught during development
- IntelliSense support: IDE provides autocomplete and type hints
- Runtime safety: Message validation can be added for production
Message Validation¶
In development mode, messages are validated strictly. In production, validation may be relaxed for performance.
Message Flow Patterns¶
- Request-Response: Webview sends command → Extension processes → Extension sends event
- Streaming: Extension sends multiple events for a single operation (e.g., LLM streaming)
- Broadcast: Extension sends events to all listeners (e.g., execution status updates)
Error Handling¶
- Invalid messages: Logged to console, may be ignored
- Missing data: Handled gracefully with default values
- Network errors: Reconnection logic in webview
Usage Examples¶
Sending a Command from Webview¶
import type { ExecuteWorkflowCommand } from './Protocol'
const message: ExecuteWorkflowCommand = {
type: 'execute_workflow',
data: {
nodes: workflowNodes,
edges: workflowEdges,
state: workflowState,
},
}
// Send to extension
vscode.postMessage(message)
Receiving an Event in Webview¶
import type { NodeExecutionStatusEvent } from './Protocol'
window.addEventListener('message', (event) => {
const message = event.data as NodeExecutionStatusEvent
if (message.type === 'node_execution_status') {
const { nodeId, status, result } = message.data
// Update UI based on node execution status
}
})
Type-Safe Message Handling¶
import type { ExtensionToWorkflow } from './Protocol'
function handleMessage(message: ExtensionToWorkflow) {
switch (message.type) {
case 'node_execution_status':
// TypeScript knows message.data is NodeExecutionPayload
console.log(message.data.nodeId, message.data.status)
break
case 'node_assistant_content':
// TypeScript knows message.data has content array
message.data.content.forEach(item => {
console.log(item.type, item.text)
})
break
// ... other message types
}
}
Related Documentation¶
- Extension API Reference - Extension API and commands
- Node Types Reference - Available node types
- Events Reference - Event system documentation