Care is a product built on the platform rather than beside it: a scheduled companion for people who benefit from a regular check-in call, typically older adults living alone. It calls, holds a real conversation, writes down what it learned, and raises an alert when something sounds wrong. Everything below the persona is Realtime and Telephony. Care contributes what a call is about; the platform contributes the call.

What happens when a call goes out

Worth reading once, because it explains where each setting takes effect and what each failure means.
1

An occurrence is materialized

The sweeper turns due schedules into care_calls rows and enqueues one dispatch job each. Scheduling is per-patient timezone-aware and DST-safe, and the occurrence index makes it idempotent — a call fires once even with several workers running.
2

Dispatch claims the row

An atomic claim with a lease, so a duplicate enqueue is a no-op and a worker that dies mid-dial does not strand the call. A call more than two hours past its scheduled time is canceled rather than dialed: a backlog must not ring a senior’s phone at a wildly wrong local time.
3

The persona is rendered

Care renders the companion prompt and the greeting into finished text — persona style, the person’s name and language, the local time of day, their memories, the last call’s summary, and any followups it left. There is no graph and no template on the platform side; the platform is handed words.
4

A session brief is staged

The instructions, the greeting and the voice are written to Redis under the call’s uuid, where the media socket will read them. If that write fails the call is not placed — a companion call in the model’s default persona is the wrong call.
5

Telnyx dials

With a signed capability in the media URL it is given at dial time, so the socket the carrier opens seconds later authenticates itself with no round trip. Answering-machine detection is requested on every call.
6

The leg becomes a realtime session

The carrier’s media socket is relayed into /v1/realtime. From here the visit is an ordinary session: same concurrency accounting, same recording, same transcript row, same per-minute billing.
The transcript is the visit. There is no second record of what was said: the speech session row carries the turns, and post-call analysis reads them.

After the call

A sweeper hands each finished call to the results task, which claims it under its own lease and takes one of two paths. Nobody was reached. Three shapes count, and they are deliberately distinguishable: no session row at all means the carrier never connected one; a row that was opened and never finalized means the worker died mid-call; and the carrier’s answering-machine verdict of machine or fax means voicemail. All three mean nobody received a visit, so all three retry while attempts remain on the schedule — max_attempts and retry_delay_minutes — and raise a warning unreachable alert when they run out. A finalized session with no words is treated differently. That call happened, and re-dialling someone who has already been spoken to is the outcome most worth avoiding. Someone was reached. The transcript is formatted and passed to one text completion against the platform’s own model, hard-capped at 90 seconds, which returns strict JSON. Its contents land in a single commit with the status flip: One commit because a partial write would be unrecoverable — the row is terminal, so nothing re-lists it — and could drop a safety alert on a call that otherwise reads as a clean visit. A call is never left mid-analysis. Any failure after the claim lands it in completed with result.extraction_error set, and a hard crash is recovered by the lease.

Call statuses

with no_answer, failed and canceled as terminal side exits. failed carries an error string — telephony_not_configured, brief_write_failed, call_initiation_failed, concurrency_limit_reached — which names infrastructure rather than a missed call. An organization at its concurrency ceiling is not a failure at all at first: schedules cluster on round times, so the call is deferred a few minutes and re-tried up to five times before it gives up.

The model

The companion is a speech-to-speech session

Care calls run on the realtime speech-to-speech model, never on a transcribe-then-think-then-speak cascade. A cascade turns a visit into a walkie-talkie exchange, which is the exact experience Care exists to avoid. The persona is one of five, set per patient in companion_config: warm_granddaughter (the default), gentle_grandson, calm_nurse, caring_friend, cheerful_companion. Each is a few sentences of voice direction rather than a rulebook, and companion_name (default Amira) is the name the companion introduces itself with. The voice resolves in order: the patient’s own companion_config.voice, then the organization’s care-wide voice setting, then the first ready female built-in. The last step exists because the platform’s fallback voice is male while the default companion is a granddaughter — inheriting it opens the call in a voice that contradicts the persona the words establish.

Before the first call

Care dials with a carrier connection, so an organization needs one before a schedule does anything. Call now resolves exactly what dispatch will resolve, so a green button can never disagree with what the call finds: See Telephony for the setup itself. GET /v1/care/settings reports telephony_configured, which means dialable, not “a row exists”.

Set up a patient

Voice intake

In the dashboard, Care → Patients → Enroll is a conversation rather than a form. A realtime session interviews you about the person you are setting up — their people, where they are from, what they love, how their day goes — and writes the enrollment form beside it as you talk, through tools it calls while listening. Every field stays editable, and you can skip the conversation entirely. What intake collects is what the companion opens its calls with. A profile with names and stories in it produces a call that sounds like a friend; an empty one produces small talk.

Memory

Memory is what makes the companion feel like it knows the person. It is written by the extraction pass and recalled at the start of the next call, and you can write it directly:
Categories are family, story, preference, health, routine, event and followup. The category is what lets the companion recall the right thing at the right moment instead of reciting everything it knows — the next call opens by asking how the visit went, which is the difference between a check-in and an interrogation.

Alerts

The companion raises alerts from what it hears — a missed medication, a fall, a marked mood change — and the retry chain raises one when a person cannot be reached at all:

Call now, and reading a call back

call_now is refused with a 400 when the organization cannot dial (the reasons above) and a 402 when it is out of credit, rather than accepting the request and failing quietly a minute later.
The recording is named here, not signed. Minting a download URL belongs to the sessions surface, and having two places decide who may hear a senior’s voice is one place too many. GET /v1/care/dashboard returns the caregiver view — recent calls, open alerts and per-patient status — in one request.

Going further

Telephony

The carrier, the relay, and the capability on the media socket.

Sessions

Transcripts, recordings and deletion for every call.

Voices

Picking the companion’s voice, and why a voice is a reference clip.

Compliance

Disclosure, consent and retention when you call people.