Pipeline Overview
Every inbound SMS flows through 13 sequential steps:- Phone Resolution — Map phone number to family → member → role → access level
- Context Loading — Load
family.md, conversation history, member profile - Pre-Filter (Enforcement) — Strip restricted sections by access level
- PHI Audit — Log context access with WHO/WHAT/WHEN/WHY
- AI Generation — Call agent with filtered context
- Post-Check (Enforcement) — Scan response for PHI leakage
- Persistence — Apply
family_file_updates(backup → edit → validate) - Logging — Record interaction in conversation timeline
- Response Return — Return SMS text + metadata to caller
- Approval Gating — High-risk edits require YES/NO confirmation
- Outreach — Send messages to other team members
- Learning — Persist corrections to
lessons.md - Routing Updates — Add new family members
Entry Point
Sender phone number in E.164 format (e.g.,
+16517037981)SMS message text from the sender
If
true, runs resolution and context assembly without calling the AI. Returns metadata for testing.Transport service type:
"SMS", "iMessage", or "RCS". Affects agent tone and confirmation mechanics.Return Value
Whether the handler completed successfully
SMS text to send back to the user
List of outreach messages to send to other team members
Result of applying edits to family.md
Resolved member information
Enforcement layer metadata
Key Functions
Phone Resolution
runtime/scripts/sms_handler.py:122
runtime/scripts/sms_handler.py:139
Context Loading
family.md + schedule.md + medications.md if they exist.
Location: runtime/scripts/sms_handler.py:185
runtime/scripts/sms_handler.py:204
System Prompt Assembly
SOUL.md(agent identity)agent_root.md(routing instructions)capabilities.md(CAN/CANNOT list)skills/*.md(conversation patterns)lessons.md(global + per-family corrections)- Channel-specific guidance (iMessage vs SMS)
- Filtered family context
- Recent conversation history
CRITICAL: The
family_context passed to this function must already be filtered by role_filter.filter_family_context(). The agent only sees what the member is allowed to see.runtime/scripts/sms_handler.py:289
AI Response Generation
sms_response(text to send)internal_notes(agent reasoning)needs_outreach(array of outreach messages)family_file_updates(edits to apply)self_corrections(lessons to persist)member_updates(member profile edits)routing_updates(new member registrations)
runtime/scripts/sms_handler.py:487
Message Logging
/conversations/{phone}/{YYYY-MM}.log(per-member timeline)/families/{family_id}/timeline/{YYYY-MM}.log(per-family timeline)
runtime/scripts/sms_handler.py:236
Response Schema
The AI returns structured JSON matching this schema:All array fields default to
[]. The schema uses strict: true mode, so the AI cannot deviate from this structure.Access Levels
Phone resolution returns one of five access levels:| Level | Sees | Can Approve |
|---|---|---|
full | All sections | Yes |
schedule+meds | Members, schedule, medications, appointments, availability, active issues | No |
schedule | Members, schedule, availability, active issues | No |
provider | Care recipient, medications, appointments, members | No |
limited | Members, care recipient (basic info only) | No |
CLI Usage
Error Handling
Unknown Phone Number
If phone resolution fails:- PHI audit logs the unknown number attempt
- Returns canned response:
"Sorry, this number isn't set up to receive messages..." - Zero PHI disclosed (hard rule)
AI Timeout/Failure
If the AI call fails after 3 retries:- Returns fallback message:
"I hit a technical glitch processing your last message, {name}. Can you send it again?" - Error logged to stderr
- No edits applied
Family Lock
All message processing for the same family is serialized viafamily_lock(family_id) to prevent race conditions when two messages arrive simultaneously.
Location: runtime/enforcement/message_lock.py
Related
- Enforcement Layer — Role filter, PHI audit, approval gating
- Linq Integration — iMessage transport layer
- Configuration — Paths, API tokens, settings