Backend¶
GiveCare's current gc-sms backend is a compact v2 Convex service for SMS
support. Current-tense architecture claims should use the v2 convex/ and
src/ files first1.
Current v2 runtime
The active backend contract is the V2 convex/ and src/ runtime. The live
system is best read as a harness-owned SMS turn pipeline with a compact Convex
schema23.
What the backend owns¶
Today the backend owns five broad kinds of state and behavior1:
- Caregiver identity and consent — phone identity, org attribution, consent timestamps, phase, and loop stage
- Message and delivery ledgers — inbound/outbound message records, Twilio SIDs, pending outbound rows, and delivery callbacks
- Care memory and assessments — namespaced memory facts plus SDOH6, CWBS14, BSFC-s, and EMA3 assessment runs with scores and zone subscores
- Safety and resources — operational
safetyEvents, groundedresourceCatalogrows, and crisis lifecycle state - Turn operations — async
jobs, per-turntraces, referral codes, and harness health reporting
Core Live Tables¶
| Group | Tables | What they hold |
|---|---|---|
| Identity + tenancy | caregivers, orgs, referrals, signupAttempts |
phone identity, org isolation, consent, journey state, SHARE codes, signup evidence |
| Messaging + jobs | messages, jobs |
inbound/outbound ledger, pending outbox rows, async turn queue |
| Memory + assessments | memory, assessmentRuns |
model-visible and harness-only facts, scored assessment history with per-zone subscores |
| Safety + resources | safetyEvents, resourceCatalog |
crisis lifecycle records, read-only grounded resources |
| Observability | traces, alertState |
per-turn evaluator decisions, token usage, cost; alert cooldown state for error-rate monitoring |
| Email + subscribers | subscribers, emailSends, emailSuppressions |
unified email list across web surfaces, send dedup ledger, suppression list |
Live Inbound Path¶
flowchart TD
A["Twilio inbound webhook"] --> B["convex/http.ts signature check"]
B --> C["agent.ingestInbound"]
C --> D{"Known caregiver?"}
D -->|No| E["Signup redirect SMS"]
D -->|Yes| F["Persist inbound message"]
F --> G["scheduler.enqueueJob"]
G --> H["scheduler.processDueJobs"]
H --> I["agent.runTurn"]
I --> J["Policy gates"]
J --> K{"Deterministic?"}
K -->|Yes| L["Commit deterministic reply"]
K -->|No| M["Build context + run Pi/Gemini"]
M --> N["Evaluate reply + effects"]
L --> O["agentDb.commitTurn"]
N --> O
O --> P["Pending outbound message"]
P --> Q["outbound sender + Twilio callback"]
Turn Execution Model¶
The current runtime separates host-owned guarantees from model-owned language and judgment2.
| Layer | Current responsibility |
|---|---|
| Policy gates | STOP/HELP/SHARE, pending consent YES, START, consent gate, crisis detection |
| Context builder | recent messages, durable/volatile memory selection, chief-of-staff brief, care guidance, resource context |
| Pi/Gemini path | open-ended support, typed capture tools, Convex-backed lookup/resources, assessment/eligibility tools, proactive turns |
| Evaluator | pre-commit checks for safety language, SMS length, clinical claims, caregiver-first posture, operational next step, and forbidden writes |
| Commit boundary | pending outbound row, approved memory writes, caregiver profile patch, assessment completion, trace, safety event, job completion |
The practical unit of orchestration is not "a model reply"; it is a committed
turn outcome. convex/agentDb.ts:commitTurn records the outbound message before
Twilio send, applies only approved memory writes, records the trace, optionally
opens a safety event, and marks the job complete. Approved follow-up requests
are enqueued through convex/scheduler.ts after the commit boundary so scheduler
policy remains centralized1.
The current turn host delegates rules that do not need Convex state to pure
modules: memory keys live in src/memoryKeys.ts, normalization and merge
semantics live in src/memory.ts, chief-of-staff posture lives in
src/turn/chiefOfStaff.ts, and policy/post-processing live in
src/turn/pipeline.ts2.
Scheduler and Outbox¶
The live scheduler is an async job queue. It claims due jobs, respects outbound
rate limits for non-inbound work, and schedules agent.runTurn for execution.
Outbound SMS uses a transactional outbox pattern: the commit inserts a pending
outbound messages row, convex/outbound.ts sends pending rows, and
convex/outboundDb.ts records Twilio delivery status1.
Related Pages¶
- SMS Journey — current v2 SMS state contract and runtime flow
- Crisis Routing — safety tier logic and crisis precedence