Skip to content

Intake Triage Scorer

Intakegate is a triage pipeline I built for messages to a children's therapy service: it proposes how soon a person should review each one, from P0, same-hour review, to P3, the lowest. This page runs its scorer, rule for rule: two safety gates, then a points total, over every combination it reads.

Original built with TypeScript · Node.js

What I found

0 of 12,672

signal combinations in which urgent wording, such as "URGENT!!!", changes the priority. Shouting is weighted zero, and every combination agrees.

0 of 10,560

combinations in which a safety gate fired and an operational signal still changed the priority: the safety gates decide before any points are added.

12 of 12

example messages from Intakegate get the same priority and classification here as from its own scorer: 1 P0, 1 P1, 9 P2, 1 P3.

Try it

The scorer sets a priority from 10 signals. Across all 12,672 combinations of them, urgent wording never changes it, and once a safety gate fires, no operational signal does.

P0 is the most urgent priority, escalated for same-hour review; P3 is the lowest. A safety gate is a rule that runs before any points are added and sets the priority on its own. Lexicon signals are matched from a fixed word list; perception signals are read from the message by a model, or by a keyless fallback. Each row counts the combinations in which changing that one signal changes the priority. Click an example to load it into the scorer below.

SignalChanges the priorityin this many of 12,672 combinationsAfter a safety gate firesin this many of 10,560Nearest exampleclick to load it
Urgent wordingLexicon0none exists
Safety lexicon matchLexiconis a safety gate
Safety concernPerceptionis a safety gate
Concern is about caregivingPerceptionis a safety gate
Same-day wordingLexicon0
Time sensitivityPerception0
Action requiredPerception0
Proposed classificationPerception0
Spam wordingLexicon0
For-information wordingLexicon0

Counts are over combinations, not messages: they say what the rules can do, not how often it happens. Everything the priority does not read is held at a complete referral.

Next to each choice, a small tag shows the priority, or else the classification, you would get by picking it.

Safety
Safety lexicon match
Safety concern
Concern is about caregiving
Operational
Same-day wording
Time sensitivity
Action required

This message matches a known patient (under Referral references), so 5 of the proposed classes become an existing patient request.

Spam wording
For-information wording
Urgent wording
Referral references: they can change the classification, never the priority
Referral references
Child named
Date of birth or age
Date of birth found by the lexicon
Parent contact
Payer
Payer found by the lexicon
Member ID
Member ID found by the lexicon
Matches a known patient
P1
Operational scoreSchedulingNo escalation · human review required

Same as Intakegate's own scorer: P1, scheduling.

Operational score

Same day, with a required action+2
Complaint with a time element+1
For information, no action-1
Spam-2
Urgent wording0
Total: P1 at +2 or more, P3 at -2 or less+2

Why

  1. Fired: Same day, with a required action +2.
  2. Score +2: P1 at +2 or more, P3 at -2 or less, P2 between.
Export or import the signals and the decision

A file holds the signals and the decision they produce. Importing rescores the signals, so a file whose decision was edited is refused.

Contents

What may move a priority?

An intake inbox is triaged by reading messages, and reading is uncertain: a model can miss a concern, invent one, or be loud about the wrong thing. Intakegate keeps reading and deciding apart. Perception, a model or a keyless fallback, only reports signals: a proposed classification, a safety read, a time read, whether action is required. A pure scorer, a set of fixed rules with no model in it, turns those signals into a priority from P0, the most urgent, to P3, and every item still goes to a person.

That separation is only worth having if the scorer's rules hold the line the design claims for them: safety before convenience, and volume never standing in for need. Rules can be tested where a model can only be sampled, so this page tests them exhaustively.

What each signal can change

The scorer reads 10 signals to set a priority. Taken together they have 12,672 combinations, and every one is scored. For each signal, the table counts the combinations in which changing that signal alone, to any other value, changes the priority.

Urgent wording changes it in 0: shouting is weighted zero, and no combination finds a way around that. In 10,560 combinations a safety gate, a rule that sets the priority before any points are added, fires, and there the seven operational signals change the priority in 0. That much holds by design; the count confirms the rules do what the design says. Of the 2,112 combinations that reach the operational score, the for-information nudge, -1, decides only 40. On its own it moves a message from 0 to -1, which is still P2. It only matters next to another nudge.

Two signals can say the same thing. Same-day wording found by the lexicon, a fixed word list, and a same-day time read from perception feed one nudge, so on a same-day reschedule neither alone decides: switch one off and the other still carries it. The scorer below opens on that message, and each option shows what choosing it would change. The counts describe what the rules can do, not how often it happens; real messages are not spread evenly over these combinations.

Where this comes from

Intakegate is a triage pipeline I built in TypeScript for synthetic intake messages to a children's speech, occupational and physical therapy service. It reads each message, scores it, and drafts the follow-up work for a person to review, without sending anything. This page is its scorer, ported rule for rule and checked against the source's own example messages.

What this page is not

Not clinical software and not clinical guidance: the messages are invented, a priority is a review proposal, and every item goes to a person. This page is the scorer only; it does not read message text.

For engineers

The scorer's rules and weights, the check of the port against the source, the rest of the pipeline, the limits in full, and how to rerun it.

How the scorer decides

Two gates, then a sum. If the lexical safety backstop matches, or perception reads a possible or clear safety concern about caregiving, the item is P0, classified safeguarding and escalated for same-hour review; nothing is summed. A safety concern that is not about caregiving makes it P1, with no escalation. Only otherwise does the operational score run, from zero: same-day with a required action +2, a complaint with a time element +1, for information with no action -1, spam -2, urgent wording 0. A score of +2 or more is P1, -2 or less P3, anything between P2.

An urgent read is not a same-day one. Only a same-day time read or same-day wording earns the +2, and only with a required action. An urgent time read earns nothing on its own: it counts only as the time element in a complaint's +1. So with its same-day wording off, moving the opening message's time read from same day to urgent takes it from P1 to P2.

Structure overrides the proposal. The classification starts from perception's proposal. Spam wins first; a proposed scheduling, clinical question, missing paperwork or safeguarding class stands; a known patient becomes an existing-patient request; a referral missing a child's name, date of birth, parent contact, payer or member ID becomes missing paperwork. The order matters: a known patient is recognized before missing references are checked.

A port, checked against the source

The rules, weights and thresholds are Intakegate's score.ts, unchanged. The port runs the source's own scorer tests, and the 12 fixture messages, as signal bundles from the source's keyless perception, score as the source scored them: 1 P0, 1 P1, 9 P2, 1 P3.

The pipeline, in detail

Intakegate runs five steps: perceive, score, orchestrate, assemble, validate. Perception always runs a lexicon. With a provider key and an explicit opt-in, it also asks a fast model for structured signals, and a stronger one when safety is flagged, confidence is low or the two readings conflict, each call on its own timeout. Orchestration then runs class-specific local queries and drafts: patient search, coverage lookup, policy notes, provider slots, tasks, unsent replies. Every action tool is a stub that records what it would have done; the agent never holds a slot.

The source is candid about where the design stops. The lexical backstop favors review over silence, so a negated phrase such as “no abuse” still fires P0. A strong model can overrule a fast model's safety read when the lexicon is silent, so the cascade is not a monotonic safety guarantee. Coverage that is not on file can still surface appointment suggestions. The source publishes no accuracy, recall or latency figures, and this page cites none.

Its limits in detail

This page is the scorer only. It does not read message text, so it cannot show perception being wrong; it shows what follows from whatever perception reports. Orchestration, drafting and validation are in the source, not here. The known-patient signal stands in for the source's literal match of two fictional patients. An exported file is checked for consistency, not authenticity: anyone can write signals that score the way the file says.

Reproduce it

Load an example from the table and read the marked signal's options; pick an example message and compare it with what the source decided; open the referral references to send a referral to missing paperwork. Under the hood, export a file, edit its decision, and import it: the file is refused. Files are limited to 20 KB. The port, the influence count, the fixtures and their tests are in the code for this page. From the site's Next.js app:

npx vitest run src/lib/projects/intake-triage src/components/projects/intake-triage