Intake Engine — Patient Intake and Evaluation
Audiences: doctor, nurse, receptionist, clinical-buyer, developer
The intake engine manages the structured pre-consultation evaluation workflow — capturing a patient's presenting complaint, clinical history, insurance, referrals, and functional assessments — and publishes real-time SSE events so the clinical team sees intake progress live.
Business Purpose
Patient intake is the structured information-gathering phase before a clinical visit. Without a systematic intake process, receptionists ask the same questions every visit, clinicians discover gaps in the chart mid-consultation, and hand-offs between staff are verbal and lossy.
Dudoxx HMS's intake engine provides:
- Structured
IntakeEvaluationrecords — Prisma-backed, linked to a patient and organization. Lifecycle:PENDING → IN_PROGRESS → COMPLETED → ARCHIVED. - Rich participant model — multiple staff members (roles:
CLINICIAN,NURSE,ADMIN,COORDINATOR) can collaborate on a single intake record. - Linked sub-documents — each intake evaluation can carry: clinical profile, referral, insurance coverage, functional assessment, placement request, conversation threads, notes, and file attachments.
- Intake rules engine — configurable
IntakeRulesGroup/IntakeRuleItemrecords (stored inddx_api_aiPrisma schema) allow clinics to define conditional intake workflows (trigger conditions, required fields by patient category). - Vector indexing —
IntakeVectorServiceindexes intake data into Qdrant for semantic search (used by the AI assistant to find relevant past intakes). - Real-time SSE —
IntakeSseHelperemitsintake.created,intake.updated,intake.status.changedevents over the organization-level SSE channel so all connected staff see intake updates instantly.
Clinics that deploy intake properly reduce consultation prep time by 40–60% and eliminate missing-information callbacks.
Audiences
- Investor: The intake engine is a differentiator for psychiatric, addiction medicine, and rehabilitation settings that require multi-party, multi-document evaluation workflows. It extends the platform beyond simple GP visit management.
- Clinical buyer (doctor/nurse/receptionist): Receptionists create intakes when patients call or arrive. Nurses add clinical profiles and functional assessments. Doctors review the completed intake before the visit. All actions stream in real-time to the clinical dashboard.
- Developer/partner:
POST /api/v1/intake-evaluationscreates an intake. Sub-resources:/participants,/notes,/conversations,/attachments,/clinical-profile,/referrals,/insurance,/functional-assessments,/placement-requests— all nested under the intake ID. Rules:GET|POST /api/v1/intake-rules-groups. - Internal (ops/support): Main intake data in Prisma
ddx_api_main(IntakeEvaluation,IntakeParticipant,IntakeNote,IntakeConversation). Rules inddx_api_ai(IntakeRulesGroup,IntakeRuleItem). Vector index in Qdrant (collection keyed per org). SSE viaEventBusService(Redis DB1).
Architecture
IntakeEvaluationController (/api/v1/intake-evaluations) owns these services:
| Service | Responsibility |
|---|---|
IntakeEvaluationService | CRUD, status machine, SSE, vector indexing |
↳ PrismaService | IntakeEvaluation, Participant, Note, Conversation |
↳ EventBusService | SSE events (intake.created, intake.updated, etc.) |
↳ IntakeSseHelper | SSE channel resolution + event publication |
↳ IntakeVectorService | Qdrant indexing for semantic search |
IntakeParticipantService | Multi-staff collaboration model |
IntakeAttachmentService | File uploads (MinIO buckets) |
IntakeNoteService | Clinical notes on intake |
IntakeConversationService | Messaging threads within intake |
IntakeLinkedEntityService | Generic entity linking (visit, appointment, etc.) |
IntakeClinicalProfileService | Structured clinical history capture |
IntakeReferralService | Referral source documentation |
IntakeInsuranceService | Insurance coverage capture |
IntakeFunctionalAssessmentService | GAF, ADL, and other functional scales |
IntakePlacementService | Placement request management |
Two further controllers:
| Controller (route) | Service | Collaborator / responsibility |
|---|---|---|
IntakeRulesGroupsController (/api/v1/intake-rules-groups) | IntakeRulesService | PrismaService — IntakeEvaluation (for org resolution) |
| ” | ” | PrismaAiService — IntakeRulesGroup + IntakeRuleItem (ddx_api_ai DB) |
IntakeRulesExecutionsController (/api/v1/intake-rules-executions) | IntakeRulesExecutorService | evaluates rules against intake data |
Dual DB pattern: Intake evaluation records use PrismaService (main DB); intake rules use PrismaAiService (AI DB). This separates clinical operational data from the AI/rules engine configuration schema.
SSE events flow through EventBusService (src/ai/tucan/sse/event-bus.service.ts) — same bus used by TUCAN AI. Events use organization-level channels via SSEChannels.organization(orgSlug).
Tech Stack & Choices
| Layer | Technology | Notes |
|---|---|---|
| Intake CRUD | Prisma ddx_api_main | IntakeEvaluation, IntakeParticipant, IntakeNote, IntakeConversation, IntakeAttachment |
| Rules storage | Prisma ddx_api_ai (PrismaAiService) | IntakeRulesGroup, IntakeRuleItem — separated from clinical data |
| SSE | EventBusService (Redis DB1, RxJS) | 5 intake event types; organization-level channel |
| Vector index | IntakeVectorService → Qdrant | Semantic search over historical intake records |
| File attachments | MinIO via StorageService | Stored in {clinic}-attachments bucket |
| Status machine | IntakeStatus enum (PENDING/IN_PROGRESS/COMPLETED/ARCHIVED) | Prisma-managed; SSE emitted on transition |
| Auth | @RequireRole() per sub-resource | @RbacExempt() on guest submission endpoints (public intake forms) |
| Priority | IntakePriority enum | Drives queue ordering in intake dashboard |
Data Flow
Receptionist creates an intake
Business outcome: A patient calls to book an appointment; the receptionist creates an intake evaluation and assigns a nurse. Both staff see the new intake appear in the dashboard within 1 second.
Technical mechanism:
POST /api/v1/intake-evaluationswith{ patientId, organizationId, priority: "HIGH", notes: "Patient reports chest pain" }.IntakeEvaluationController.create()(intake-evaluation.controller.ts:80) resolves role via@RequireRole(DOCTOR, NURSE, CLINIC_ADMIN, ...).IntakeEvaluationService.create()(intake-evaluation.service.ts:34): a. ResolvesorganizationId— accepts UUID or slug (resolveOrganizationId(),intake-evaluation.service.ts:57). b. CreatesIntakeEvaluationPrisma row with statusPENDING. c. CallsIntakeSseHelper.emitCreated()→ publishesintake.createdevent toSSEChannels.organization(orgSlug)viaEventBusService. d. CallsIntakeVectorService.indexIntake()to add to Qdrant for semantic recall.- All clinical staff with active SSE connections receive the event immediately.
Intake rules evaluation
POST /api/v1/intake-rules-executions with intake ID → IntakeRulesExecutorService loads applicable IntakeRulesGroup from ddx_api_ai, evaluates each IntakeRuleItem's condition against the intake data, returns pass/fail results and recommended next steps.
Intake completion + summary
PATCH /api/v1/intake-evaluations/:id with status: "COMPLETED" → IntakeEvaluationService transitions status, emits intake.status.changed SSE event, triggers IntakeSummaryService to generate a structured summary (used by the attending doctor as pre-visit brief).
Implicated Code
ddx-api/src/clinical-forms/intake-evaluation/intake-evaluation.controller.ts:60—IntakeEvaluationController— 11 injected sub-services;@Controller('intake-evaluations')ddx-api/src/clinical-forms/intake-evaluation/intake-evaluation.controller.ts:80—POST /intake-evaluations— entry point for intake creationddx-api/src/clinical-forms/intake-evaluation/intake-evaluation.service.ts:26—INTAKE_EVENTS— SSE event type constants (intake.created,intake.updated,intake.status.changed,intake.archived,intake.ownership.transferred)ddx-api/src/clinical-forms/intake-evaluation/intake-evaluation.service.ts:34—IntakeEvaluationService— orchestrates Prisma + SSE + Qdrant for each lifecycle actionddx-api/src/clinical-forms/intake-evaluation/intake-evaluation.service.ts:57—resolveOrganizationId()— accepts UUID or slug; queries Prismaorganizationtable by multiple fieldsddx-api/src/clinical-forms/intake-evaluation/intake-sse.helper.ts:1—IntakeSseHelper— SSE channel resolution + event emission wrapperddx-api/src/clinical-forms/intake-evaluation/intake-vector.service.ts:1—IntakeVectorService— Qdrant indexing for semantic intake searchddx-api/src/clinical-forms/intake-evaluation/intake-rules.service.ts:19—IntakeRulesService— uses dual-DB:PrismaService(org resolution) +PrismaAiService(rules data)ddx-api/src/clinical-forms/intake-evaluation/intake-rules.service.ts:59—createGroup()— createsIntakeRulesGroupinddx_api_aiDBddx-api/src/clinical-forms/intake-evaluation/intake-summary.service.ts:1—IntakeSummaryService— generates structured intake summary for doctor pre-brief
Operational Notes
- Dual DB for rules: Intake rules (
IntakeRulesGroup,IntakeRuleItem) live inddx_api_ai— notddx_api_main.IntakeRulesServiceusesPrismaAiService, not the defaultPrismaService. ConfirmAI_DATABASE_URLis configured if rules creation returns 500. - SSE channel is org-scoped: Intake SSE events go to
SSEChannels.organization(orgSlug)— all staff in the same org receive them. No per-user filtering — clinic staff UI must filter by assigned participant if needed. - Organization ID slug resolution:
IntakeEvaluationService.resolveOrganizationId()accepts both UUID and slug. The X-Clinic-ID header contains the slug — the service translates it. Do not assume UUID in intake-specific code. - Qdrant vector indexing:
IntakeVectorServiceindexes intake records for semantic search. If Qdrant is unavailable at create time, the indexing failure is logged but does NOT block intake creation (graceful degradation). - Guest submission:
GuestSubmissionsController(guest-submissions.controller.ts) provides@RbacExempt()endpoints for unauthenticated patient-facing intake form submissions. Validate CSRF/rate-limit on this surface before exposing to the internet.
Related Topics
- Clinical Visits — Intake may be linked to a visit via
IntakeLinkedEntityService - Clinical Forms — Assessment forms used within intake workflows
- Assessments — Functional assessment scales (GAF, ADL) captured in intake
- Clinical Activities — Intake events appear in patient activity timeline
- Diagnosis Engine — Intake summary feeds diagnostic evaluation