This is a submission for the Sanity Challenge, Path Two: Vibe-Code Something Strange
What I Built
I have watched people close to me go through dementia, and it changes what you ask of technology.
The small things become high-stakes: whether it is time for a pill, who is coming to visit, what to say to someone who is frightened and wants to go home. A confident wrong answer from an AI companion is not an inconvenience here. Reading out a medication step from an order that was replaced last week, or telling a scared person that someone is on the way when nobody is, can do real harm. So the question behind this project was: how do I build an agent that only says what the care records support, and says "let's check with your family" when they don't?
Project Anchor is my answer. It is an ambient care companion for people living with dementia, and for the family who look after them.
The patient sees a calm bedside kiosk: a greeting, today's chores as numbered steps with safety notes, a gentle AI companion (text and optional voice), and Memory spark, a face-and-name game. When the companion senses distress or an emergency, it raises an alert. A Sanity Workflow stored next to the content drafts a briefing for a family caregiver. The caregiver takes the alert, then approves it or sends it back with a reason, and Anchor redrafts.
The strange part is that the process is data. The agent and the human move the same workflow instance through the same transitions, and the stage history lives in the dataset beside the patients, medications and memories it concerns.
All patients, families and stories are fictional demo data. Anchor is not a medical device and never diagnoses or gives medical advice.
Demo
- Live app: https://project-anchor-one.vercel.app/kiosk
- Caregiver alerts: https://project-anchor-one.vercel.app/caregiver/alerts. Sign in as Emily Miller with passcode Test1234.
A 3-minute path for judges (it matches the video below, and uses only the public app, so no Studio access is needed):
-
Ask who is visiting. Open
/kiosk, choose Margaret Miller, and ask Anchor "Who is visiting me today?" Anchor answers from the visit documents in Sanity, and says who is coming, or that nobody is scheduled. - Look ahead. Ask "What about next week?" Anchor widens the same query to the coming week and names the visitors and when they arrive. A cancelled visit would not appear.
- Say something alarming. Type "I feel dizzy and my chest hurts." Anchor stays calm, tells her to stay seated, and says her care team has been told. It promises nothing it can't know. A medical-emergency alert is raised behind the scenes.
-
Review as the caregiver. Open
/caregiver/alertsand sign in as David Miller with passcode Test1234. The alert appears with Anchor's briefing and a suggested response. For a medical emergency, the first step is to check on her and make sure emergency help is called. - Take it, then decide. Click Take this alert. Then either Approve it, or Send back with a reason and watch Anchor redraft the briefing before you approve it. Either way, the alert resolves and leaves the list.
Code
https://github.com/pradeepdepuru/project-anchor
Next.js 16 and React 19 on the front, Sanity Studio 5 behind it, deployed on Vercel. The agent endpoint is frontend/app/api/agent/route.ts, the workflow is studio/workflows/alert-response.ts, and the caregiver review screen is frontend/app/caregiver/alerts/.
What's in the Studio
I treated the Studio as the control panel for the whole care experience. Here is each desk item, and the Sanity feature behind it.
Kiosk Settings is a singleton that controls the kiosk without a code change: a Show Chat Companion toggle, a theme (Dark, Light or High Contrast) and an optional custom welcome line. Publish it and the kiosk changes on refresh. Behind it: a settings document, plus next-sanity live content (<SanityLive />).
Patients, and Caregivers & Family are both person documents, split by an isPatient flag in a curated desk structure. To add a patient, open Patients, click +, tick isPatient, and add a picture, a slug and memory stories. To add a caregiver, open Caregivers & Family, click +, set their relationship (daughter-in-law, grandson, son, granddaughter) and use the patient reference to link them to the person they support. Reference fields are filtered, so alerts can only point at a real patient. Each person carries coreMemories[] (title, story, era), the comforting stories Anchor can draw on. Margaret's, for example, includes the phrase "The kitchen is clean and the timer is set." Behind it: references, filtered reference fields and a custom desk structure.
Chores by patient holds dailyChore documents: a scheduled time, instructions, completions and safety parameters (priority, assistance level, supervision, precautions). Arthur's morning medication chore carries a choking-risk note that the kiosk shows beside the steps. A custom Verify Completion document action lets a caregiver confirm a completion the patient reported. Behind it: a custom Studio document action and structured safety fields.
Medication orders are versioned in the content. A new order can supersede an older one, and the current order is the one that no newer effective order replaces. Publish a replacement with different steps and Anchor reads the new steps the next time it is asked. Behind it: a self-reference in the schema, queried with GROQ.
Visits link a patient to a visitor with a start, end, purpose and status (scheduled or cancelled). Set a visit to Cancelled and Anchor stops mentioning that visitor when asked who is coming today. Behind it: references, a status field and GROQ date-window filters.
Open alerts are careAlert documents raised by Anchor, typed as medical emergency, safety hazard or distress, with a status of open, acknowledged or resolved. The briefing, suggested response and workflow instance ID are written by the agent and are read-only in Studio. Behind it: Sanity Workflows (below).
Cognitive Log records each Memory spark session: date, game type, score, accuracy rate, how the patient responded and caregiver notes.
Anchor Log records every companion turn: the question, the answer, the GROQ queries it ran, the documents it read, whether it fell into safe mode and whether it raised an alert. It is both an audit trail for a family and a debugging tool, and I used it constantly while tuning.
How It Uses Sanity
The care circle is the dataset. Every patient and every caregiver is a document, and the relationships between them are references: a caregiver points at the patient they support, a visit points at a patient and a visitor, an alert points at a patient. There is no separate user table and no hand-written knowledge file. Adding a person in the Studio and linking them is all it takes: the kiosk directory shows them, and the agent can reason over them. The README's setup is literally "create patients and caregivers, link each caregiver to a patient, publish." That makes this a strong fit for structured content. A family can describe the people in their own care circle in a form, and the same documents serve the kiosk, the agent and the review workflow.
An agent grounded in the content graph. Anchor queries the dataset through the Sanity Context MCP with a groq_query tool. "Who is visiting me today, and how do I know them?" joins visits, people and their memory stories. A keyword search can't tell that a medication order was replaced or that a visit was cancelled. Relationships and states can, and that is the difference between an answer you can trust and one you can't. The browser sends only { patientId, messages, timeZone }, and the server resolves everything else from Sanity, so the client cannot inject facts. If the records are missing or the MCP is unreachable, Anchor drops into safe mode: it may comfort the patient but must not state facts about them, and it points to the family instead.
Workflows. The alert-response workflow moves each alert through raised → review → resolved, with a rejection loop back to Anchor:
raised --(Anchor submits briefing)--> review --(caregiver approves)--> resolved
^ |
+--------(caregiver sends back)--------+
Anchor drafts the briefing from the conversation and the patient's memory anchors. The caregiver takes the alert, then approves it or sends it back with a reason, which makes Anchor redraft. In a setting like dementia care, this keeps a person in charge of what the agent suggests, and the whole history is stored with the content. Duplicate alerts of the same type within 10 minutes are ignored.
A custom review interface. The official Workflows Studio plugin needs Sanity Studio 6, and this project runs 5.31.1. A major Studio upgrade the week of the deadline felt like a bad bet, so I built the review screen as a Next.js page (/caregiver/alerts) that fires the same workflow actions from the server. Sign-in is a shared family passcode plus a chosen name. That is demo-grade, and I say so in the README.
What I did not build: the App SDK dashboard. I put the time into Workflows and the agent's behavior instead.
My Build Process
I used Antigravity + Claude to build the app. The most useful prompting was not clever wording. It was testing with real content and tightening rules whenever the output was subtly wrong. Here is what went wrong.
The Studio plugin needed a newer Studio. I'd planned to use the Workflows plugin for approvals. Its requirements were a major version above mine, so I built the custom panel instead.
A schema warning a judge would see. The agent writes three fields onto each alert (workflow instance, briefing, suggested response). Studio showed an "Unknown fields found" warning until I added them to the schema as read-only fields and redeployed Studio. A hard refresh was needed to clear the cached schema.
Anchor promised help was coming. My prompt told it to say help was on the way. It then told a scared patient a caregiver would "arrive". The agent can't know that. The tool only confirms the care team was notified, so I rewrote the rule to never promise an arrival.
Anchor said everything twice. The kiosk reply repeated itself because the model wrote a reply, called the alert tool, then wrote the reply again. The Anchor Log showed one clean copy, which confirmed the model was the cause and not the UI. I added a rule to say nothing before the alert tool and to reply once afterwards.
Right anchor, wrong moment. This was the most interesting failure, because nothing was invented. Anchor drafted a suggestion for a caregiver to say to Margaret: "David checked the perimeter and locked up for the night." That sentence is a real stored comfort phrase, but it was written for her bedtime lock-checking, and the alert came at 4 PM. It also turned "Emily still brings a tin of cookies when she visits" into "Emily's cookies are on the way". I added a rule to use an anchor only when its situation fits. That overcorrected: Anchor then skipped all of Margaret's anchors, including a general comfort phrase. Fixing that exposed a worse case: for chest pain, the suggestion told the caregiver to steer the conversation toward baking. The final rules separate the alert types. For distress, general comfort anchors fit, and anchors tied to a specific time or situation are skipped when they don't match. For a medical emergency, the first step must be to check on the patient and make sure the care team or emergency help has been called.
Anchors are topics, not facts. One anchor was Arthur's dog Rex from the 1990s. An early reply said Rex was "right there with you". I changed the prompts so memories are things to talk about, never statements about who or what is present now.
Retests were silently blocked. The 10-minute duplicate guard returned the existing alert, so a retest looked like nothing had changed. I learned to resolve old alerts before each retest.
Workflows is a prerelease. The packages' optional TypeScript peer conflicts with my version, so installs use legacy-peer-deps, and the CLI's inspection commands need a newer @sanity/cli-core than the Studio does. Both are listed under known limitations in the README.
Sanity Project Details
-
Project ID:
t3retdwe(datasetproduction) - Studio (sign-in required): https://www.sanity.io/@oky0bdg3q/studio/osxe94h1xsq6ws70jhwlhigy/default
-
Document types:
person,dailyChore,medicationOrder,visit,careAlert,anchorLog,cognitiveLog,kioskSettings, plus thealert-responseworkflow definition
Top comments (0)