Skip to content

IntuMessage

IntuMessage is the standard message envelope that flows through every pipeline stage. Regardless of the source protocol — HTTP, TCP, Kafka, file — the raw payload is wrapped in an IntuMessage before entering the pipeline. Transformers, validators, and filters all receive and return this object.

interface IntuMessage {
id: string;
correlationId: string;
channelId: string;
body: any;
contentType: string;
transport: string;
sourceCharset: string;
timestamp: string;
metadata: Record<string, string>;
version: number;
}
PropertyTypeDescription
idstringUnique message identifier (UUID v7), assigned at ingestion
correlationIdstringGroups related messages (e.g. a request and its response, or batch siblings)
channelIdstringThe channel that is processing this message
bodyanyThe parsed message payload — an HL7v2 object, FHIR resource, JSON, XML DOM, etc.
contentTypestringFormat of the body (hl7v2, fhir+json, json, xml, x12, csv, etc.)
transportstringSource protocol: http, tcp, kafka, file, smtp, dicom, database, etc.
sourceCharsetstringCharacter encoding of the original payload (e.g. UTF-8, ISO-8859-1)
timestampstringISO 8601 timestamp of when the message was received
metadataRecord<string, string>Transport-specific metadata (see below)
versionnumberSchema version for forward-compatible evolution of the envelope format

The metadata map is populated with keys that depend on the source transport. This provides access to protocol-level details without polluting the core interface.

KeyExample
http.methodPOST
http.path/api/hl7/adt
http.queryfacility=MAIN&format=json
http.remoteAddr10.0.1.42:54321
http.header.<name>http.header.Content-Typeapplication/json
KeyExample
kafka.topichl7.adt.inbound
kafka.partition3
kafka.offset284710
kafka.keyPATIENT-12345
kafka.header.<name>kafka.header.sourceepic
KeyExample
tcp.remoteAddr10.0.1.42:54321
tcp.localAddr0.0.0.0:6661
KeyExample
file.path/data/incoming/ADT_A01.hl7
file.nameADT_A01.hl7
file.size2048
file.modTime2026-03-15T08:30:00Z
KeyExample
smtp.fromlab@hospital.org
smtp.toresults@clinic.com
smtp.subjectLab Results - Patient 12345
smtp.date2026-03-15T08:30:00Z
KeyExample
dicom.callingAEPACS_MAIN
dicom.calledAEINTU_ROUTER
dicom.sopClassUID1.2.840.10008.5.1.4.1.1.2
KeyExample
database.driverpostgres
database.tableoutbound_queue
database.columnsid,patient_id,message_body,created_at

When a message is persisted to storage, exported, or queued for replay, it is serialized as .intuJSON — the canonical envelope format:

{
"version": 1,
"id": "019505a1-7c44-7f8e-b4a2-3c8d1e9f0a6b",
"correlationId": "019505a1-7c44-7f8e-b4a2-3c8d1e9f0a6b",
"channelId": "adt-to-fhir",
"contentType": "hl7v2",
"transport": "tcp",
"sourceCharset": "UTF-8",
"timestamp": "2026-03-15T14:23:01.847Z",
"metadata": {
"tcp.remoteAddr": "10.0.1.42:54321",
"tcp.localAddr": "0.0.0.0:6661"
},
"body": {
"MSH": {
"1": "|",
"2": "^~\\&",
"3": "EPIC",
"4": "MAIN_CAMPUS",
"5": "INTU",
"6": "ROUTER",
"7": "20260315142301",
"9": { "1": "ADT", "2": "A01" },
"10": "MSG-00042",
"11": { "1": "P" },
"12": "2.5.1"
},
"PID": {
"3": [{ "1": "12345", "5": "MR" }],
"5": [{ "1": "DOE", "2": "JOHN" }],
"7": "19850315",
"8": "M"
},
"PV1": {
"2": "I",
"3": { "1": "4N", "2": "412", "3": "A" },
"19": "V00098765"
}
}
}

The version field enables schema evolution. Consumers should check the version and handle unknown fields gracefully to maintain forward compatibility.

Every TypeScript function receives an IntuContext alongside the message. It provides access to runtime services and scoped state:

interface IntuContext {
channelId: string;
messageId: string;
destinationName: string;
globalMap: Map<string, unknown>;
channelMap: Map<string, unknown>;
connectorMap: Map<string, unknown>;
responseMap: Map<string, unknown>;
logger: Logger;
}
PropertyDescription
channelIdID of the channel processing this message
messageIdSame as IntuMessage.id — the unique message identifier
destinationNameName of the current destination (only set in destination-scoped stages)
globalMapShared across all channels for the lifetime of the engine
channelMapScoped to the current channel
connectorMapScoped to the current connector instance
responseMapScoped to the current message’s request-response lifecycle
loggerStructured logger with channel and message context pre-attached
export default function transform(msg: IntuMessage, ctx: IntuContext) {
const messageType = msg.body.MSH[9][1]; // "ADT"
const patientId = msg.body.PID[3][0][1]; // "12345"
const lastName = msg.body.PID[5][0][1]; // "DOE"
ctx.logger.info("Processing admission", { messageType, patientId });
return msg;
}
import { v4 as uuid } from "uuid";
export default function transform(msg: IntuMessage, ctx: IntuContext) {
const pid = msg.body.PID;
msg.body = {
resourceType: "Patient",
id: uuid(),
identifier: [
{
system: "http://hospital.org/mrn",
value: pid[3][0][1],
},
],
name: [
{
family: pid[5][0][1],
given: [pid[5][0][2]],
},
],
gender: pid[8] === "M" ? "male" : pid[8] === "F" ? "female" : "unknown",
birthDate: `${pid[7].slice(0, 4)}-${pid[7].slice(4, 6)}-${pid[7].slice(6, 8)}`,
};
msg.contentType = "fhir+json";
return msg;
}
export default function transform(msg: IntuMessage, ctx: IntuContext) {
const sourceIp = msg.metadata["tcp.remoteAddr"];
const facilityMap = ctx.globalMap.get("facilities") as Map<string, string>;
if (facilityMap?.has(msg.body.MSH[4])) {
msg.metadata["facility.name"] = facilityMap.get(msg.body.MSH[4])!;
}
ctx.responseMap.set("accepted", true);
return msg;
}