Standards-Based Internode Communication
This page documents the canonical approach to node-to-node communication in NetPad, following the new standards-based architecture (NodeMessage, AG-UI, A2A). It is intended for developers, integrators, and advanced users building or debugging workflows.
Why Standards-Based Communication?
- AG-UI compatibility: Enables rich, schema-driven UI for prompts and HITL (human-in-the-loop) workflows.
- A2A (Agent-to-Agent): Supports multi-agent, tool, and human collaboration patterns.
- MongoDB friendly: All messages are JSON, easily persisted and indexed.
- Traceability: Every step and message is auditable and replayable.
NodeMessage: The Canonical Envelope
All node-to-node communication is encapsulated in a NodeMessage envelope. This structure is designed for:
- Context propagation
- Multi-port I/O
- AG-UI prompt schemas
- Easy persistence in MongoDB
{
messageId: "uuid", // Unique message id (for trace/audit)
from: "nodeId", // Originating node's id
to: "nodeId", // Target node's id (or null for broadcast)
fromPort: "outputPort", // Output port of the sender node (optional)
toPort: "inputPort", // Input port of the receiver node (optional)
type: "NodeMessage", // Constant identifier
timestamp: "ISO8601", // When message was sent
payload: {}, // Data being sent (any JSON-serializable object)
context: {}, // Shared context (variables, global state, user info, etc)
trace: [ // Message trace/history (array of NodeMessages or step refs)
{ nodeId: "...", port: "...", time: "...", ... }
],
meta: { // Optional metadata (debugging, UI, AG-UI schema, etc)
stepId: "...", // Step/execution context id
userInputNeeded: false, // If true, triggers pause/HITL UI
uiSchema: {}, // JSON schema or AG-UI schema for frontend prompt rendering
status: "pending|done|error",
error: null // Error message if applicable
}
}Example: NodeMessage Helper
import { v4 as uuidv4 } from 'uuid';
function createNodeMessage({
from, to, fromPort, toPort, payload, context, meta = {}, trace = []
}) {
return {
messageId: uuidv4(),
from,
to,
fromPort,
toPort,
type: "NodeMessage",
timestamp: new Date().toISOString(),
payload,
context,
trace,
meta: {
...meta,
status: meta.status || "pending"
}
};
}AG-UI & HITL: Prompt Node Example
Prompt nodes emit NodeMessages with meta.userInputNeeded: true and a uiSchema for the frontend. The execution engine pauses, the UI renders the prompt, and user responses are injected as new NodeMessages.
export async function runPromptNode(node, { context, inputs, onUserInputNeeded }) {
const uiSchema = {
title: node.label || "User Input Required",
type: "object",
properties: {
[node.id + "_response"]: {
type: "string",
title: node.params.prompt || "Please provide input:"
}
},
required: [node.id + "_response"]
};
const message = createNodeMessage({
from: node.id,
to: null,
fromPort: "output",
payload: null,
context,
meta: {
userInputNeeded: true,
uiSchema,
status: "pending"
},
trace: []
});
if (onUserInputNeeded) {
onUserInputNeeded(uiSchema, node.id, message);
return message;
}
if (context.userInput) {
const response = context.userInput[node.id + "_response"];
return createNodeMessage({
from: node.id,
to: null,
fromPort: "output",
payload: { response },
context,
meta: { status: "done" },
trace: []
});
}
throw new Error("Prompt node called without onUserInputNeeded or user input in context");
}MongoDB Trace: Full Run History
All NodeMessages are appended to the workflow run’s trace array in MongoDB:
{
workflowId: ObjectId,
status: "running|paused|done|error",
currentNodeId: "nodeId",
context: {}, // Latest shared context
portData: {}, // Outputs for each node/port
trace: [ NodeMessage ],// FULL message/step history for replay/debug
pendingInput: { nodeId, uiSchema } // If paused for HITL
}Visual: Node-to-Node Message Flow
Q&A
1. Does NetPad support A2A (Agent-to-Agent) communication?
Yes. With the NodeMessage standard, any node—including agent nodes—can send and receive messages to/from other agent nodes. The message envelope includes metadata (node type, role, etc.) so agent-to-agent (A2A) and multi-agent workflows are fully supported. This enables advanced patterns such as agent collaboration, delegation, and tool use.
2. How does this refactor persist internode, inter-step communication?
All node-to-node communication is encapsulated in NodeMessages, which are appended to the workflow run’s trace array in MongoDB. Each message records sender, receiver, ports, payload, context, and metadata. This provides a complete, auditable, and replayable history of all internode and inter-step communication for every workflow run.
3. How is AG-UI implemented in this refactor?
Prompt nodes emit NodeMessages with meta.userInputNeeded: true and a uiSchema (AG-UI compatible JSON schema) for the frontend. When user input is required, the execution engine pauses and the UI renders the prompt using the provided schema. User responses are injected as new NodeMessages, resuming execution. This pattern is fully compatible with AG-UI and supports HITL (human-in-the-loop) workflows.
4. Will this refactor break pre-existing workflows/diagrams?
No, not immediately. The refactor includes transitional support for legacy raw values: older nodes and diagrams will have their outputs wrapped in NodeMessages at runtime, with warnings logged. This ensures backward compatibility while encouraging migration to the new standard. A deprecation plan and migration guide will be provided for a smooth transition.
For more, see the AG-UI documentation and Handlebars documentation.