Channel Destination

Route messages to another intu channel for multi-stage processing and channel chaining.

Overview

The Channel destination routes processed messages to another intu channel for further transformation and delivery. This enables multi-stage processing pipelines where a single inbound message can be split, enriched, or filtered across multiple channels. Channel chaining is useful for separating concerns -- for example, one channel normalizes incoming data while downstream channels handle routing to different destinations based on message content.

Configuration

Define a Channel destination in your root intu.yaml under the destinations key:

yaml
# intu.yaml
destinations:
  notification-channel:
    type: channel
    channel:
      target_channel_id: patient-notifications

Properties

target_channel_id string required
The ID of the target channel to route messages to. This must match the name field of an existing channel defined in channels/. The target channel receives the message as if it arrived from its own source.
Note The target channel must exist in the project. The intu validate command checks that all channel destination references resolve to valid channels. Circular references (A routes to B, B routes to A) are detected and rejected during validation.

Full Example

Receive HL7v2 ADT messages, normalize them in a primary channel, then route to separate downstream channels: one for FHIR server updates and another for email notifications.

Root Configuration

yaml
# intu.yaml
destinations:
  fhir-update-channel:
    type: channel
    channel:
      target_channel_id: adt-to-fhir

  notification-channel:
    type: channel
    channel:
      target_channel_id: adt-notifications

  fhir-server:
    type: http
    http:
      url: https://fhir.hospital.org/fhir/R4
      method: POST
      headers:
        Content-Type: application/fhir+json
      auth:
        type: bearer
        token: ${FHIR_TOKEN}

  alert-email:
    type: smtp
    smtp:
      host: smtp.hospital.org
      port: 587
      from: intu@hospital.org
      to:
        - admissions@hospital.org
      subject: "ADT Alert: ${eventType} - ${patientName}"
      auth:
        username: ${SMTP_USER}
        password: ${SMTP_PASS}

Primary Channel (Router)

yaml
# channels/adt-router/channel.yaml
name: adt-router
description: Receive and normalize ADT messages, then route to downstream channels

source:
  type: tcp
  tcp:
    port: 6661
    mode: mllp

destinations:
  - fhir-update-channel
  - notification-channel

Downstream Channel (FHIR Updates)

yaml
# channels/adt-to-fhir/channel.yaml
name: adt-to-fhir
description: Transform normalized ADT data to FHIR and push to server

source:
  type: channel

destinations:
  - fhir-server

Downstream Channel (Notifications)

yaml
# channels/adt-notifications/channel.yaml
name: adt-notifications
description: Send email alerts for specific ADT event types

source:
  type: channel

destinations:
  - alert-email

Router Transformer

typescript
// channels/adt-router/transformer.ts
import { Message, Context } from "@intu/sdk";

interface NormalizedAdt {
  eventType: string;
  patientId: string;
  patientName: string;
  mrn: string;
  dateOfBirth: string;
  gender: string;
  visitNumber: string;
  admitDate: string;
  department: string;
  attendingPhysician: string;
}

export default function transform(msg: Message, ctx: Context): Message {
  const hl7 = msg.body;
  const msh = hl7.segments?.find((s: any) => s.name === "MSH");
  const pid = hl7.segments?.find((s: any) => s.name === "PID");
  const pv1 = hl7.segments?.find((s: any) => s.name === "PV1");

  const normalized: NormalizedAdt = {
    eventType: msh?.fields[8]?.components[1] ?? "A01",
    patientId: pid?.fields[3]?.components[0] ?? "",
    patientName: `${pid?.fields[5]?.components[1] ?? ""} ${pid?.fields[5]?.components[0] ?? ""}`.trim(),
    mrn: pid?.fields[2]?.components[0] ?? "",
    dateOfBirth: pid?.fields[7]?.components[0] ?? "",
    gender: pid?.fields[8]?.components[0] ?? "",
    visitNumber: pv1?.fields[19]?.components[0] ?? "",
    admitDate: pv1?.fields[44]?.components[0] ?? "",
    department: pv1?.fields[3]?.components[0] ?? "",
    attendingPhysician: pv1?.fields[7]?.components[1] ?? "",
  };

  ctx.logger.info(`Routing ADT ${normalized.eventType} for patient ${normalized.patientId}`);

  return {
    ...msg,
    body: normalized,
    headers: {
      ...msg.headers,
      eventType: normalized.eventType,
      patientName: normalized.patientName,
    },
  };
}
Tip Channel chaining works well for fan-out patterns. A single inbound message can be processed by multiple downstream channels in parallel, each applying its own transformation and routing logic.