Welcome back! In the previous chapter, we explored Swabble, giving our system "ears" to listen for commands locally.
We now have a complete system: a Gateway (the brain), a Control UI (the dashboard), and various Nodes like iOS and Android (the bodies).
However, we have a hidden danger. Imagine if the iOS Node sends a message saying: {"text": "Hello"} but the Gateway is programmed to expect: {"message": "Hello"}. The Gateway won't understand, and the command will fail.
To prevent this chaos, we need a strict rulebook that everyone agrees to follow. We need the ProtocolSchema.
In a team of people, communication works best when everyone speaks the same language and uses the same grammar. In a network of computers, this is even more critical. Computers are not good at guessing; they need exact instructions.
The ProtocolSchema is a single file located at dist/protocol.schema.json. It acts as the "Dictionary" or "Constitution" of OpenClaw. It defines exactly what a message must look like to be accepted by the system.
The Central Use Case:
You are writing a new script for the Control UI. You want to tell the Gateway to "Stop." You check the ProtocolSchema, which tells you that you must send a message with type: "COMMAND" and action: "STOP". If you forget the action, the Gateway will reject your message immediately.
We use a standard format called JSON Schema to define our rules.
Think of the schema as a legal contract. Both the Sender (e.g., your iPhone) and the Receiver (the Gateway) agree that all messages will follow this specific structure.
This is the "Bouncer" at the door. When a message arrives at the Gateway, it is automatically checked against the schema. If the message doesn't match the rules (e.g., missing a required field), it is thrown out before it can crash the system.
Every message in OpenClaw is a "Packet." The schema forces every packet to have at least a type (what is this?) and a payload (the data).
You don't usually "run" the schema; you use it as a reference when writing code. Let's look at how to structure a valid message based on the rules.
dist/protocol.schema.json)
Here is a simplified view of what the schema looks like. It says: "A message is an object. It must have a type."
{
"$id": "OpenClawProtocol",
"type": "object",
"required": ["type", "payload"],
"properties": {
"type": { "type": "string" },
"payload": { "type": "object" }
}
}
Explanation:
"required": ["type"]: This means if you send a message without a type, it is illegal."payload": This is where the actual data (like "Turn on lights") goes.Based on the rules above, here is how the Control UI would send a valid command in JavaScript.
// A valid message that passes the test
const validPacket = {
type: "COMMAND",
payload: {
action: "RUN_SCRIPT",
scriptName: "DailyReport"
}
};
If you try to cut corners, the system catches you.
// This will be REJECTED by the Gateway
const badPacket = {
// Missing "type"!
cmd: "Do something",
data: "Important info"
};
What happens:
badPacket.type is missing.Invalid Protocol: Missing property 'type'.How does the Gateway actually use this JSON file to police the traffic?
Every time a WebSocket message arrives, it goes through a checkpoint.
The Gateway uses a library (often ajv in Node.js) to load the schema file and create a validator function.
1. Loading the Schema: When the Gateway starts, it reads the file.
import Ajv from 'ajv';
import schema from '../dist/protocol.schema.json' assert { type: 'json' };
const ajv = new Ajv();
// Compile the rules into a fast function
const validate = ajv.compile(schema);
Explanation:
ajv.compile(schema) creates a highly optimized function called validate. We use this function on every single incoming message.2. enforcing the Rules: Inside the WebSocket connection handler (discussed in Chapter 1), we apply the check.
ws.on('message', (rawText) => {
const packet = JSON.parse(rawText);
// Run the validation function
const isValid = validate(packet);
if (!isValid) {
console.error("Invalid packet received:", validate.errors);
return; // STOP! Do not process further.
}
// If we get here, the message is safe to use
processPacket(packet);
});
Explanation:
validate(packet) returns true or false.false, we simply stop. This protects the Gateway from crashing due to weird data sent by a buggy Android Node or a hacker.
3. Sharing the Schema:
The beauty of dist/protocol.schema.json is that it can be shared.
In this chapter, we learned about the ProtocolSchema.
dist/protocol.schema.json.We have now built the Brain, the Dashboard, the Bodies, the Ears, and the Language. Our application is complete!
But... it currently runs on your messy laptop with manual commands. To make this a professional, reliable service that runs 24/7, we need to package it up neatly.
Next Chapter: Docker Deployment
Generated by Code IQ