Inspiration

Frank called his daughter three times last week asking who Marcus is. Marcus is his grandson. He's eight. Frank is one of 55 million people worldwide living with dementia.

He doesn't forget because he doesn't care. He forgets because dementia takes memories before it takes people. And the people who love him remember everything.

Folkore started from watching this happen — not once, but in families everywhere. The gap between "the family remembers" and "the patient remembers" felt solvable. Not with a medical device or a care app — with voice, memory, and the people who matter. When Frank asks Alexa who Marcus is, Folkore doesn't pull from a general AI trained on the internet. It pulls from the specific things his daughter chose to tell Folkore — that Marcus is eight, that he wants to be a palaeontologist, that Frank calls him his little dinosaur guy. That distinction is the whole point.


What it does

Folkore is a voice-first memory companion for dementia patients and the families who care for them.

A family member sets up Folkore once — talking to Alexa to add memories: names, stories, places, moments that matter. Each memory is stored with who, what, when, and tags. Relationships are extracted automatically into a memory graph — Marcus links to his memories, Lake Tahoe links to its stories.

When Frank talks to Alexa and can't remember his grandson's name, Folkore retrieves the right memories and responds warmly: "That's Marcus — your grandson. He's eight and absolutely loves dinosaurs. He always brings a new dinosaur fact when he visits — and he has a big school project coming up he can't wait to tell you about."

When Frank says something that signals confusion — "What year is it?" or "I don't know who Dorothy is" — a dedicated LLM classifier catches it in parallel with the response, logs a typed confusion signal (temporal, person, or place), and the Alexa ring pulses amber. The family sees it in the weekly digest without Frank having to say a word about it.

Every morning, Alexa surfaces a memory for Frank unprompted — before he says a word — from his personal graph. The automatic daily trigger (EventBridge) is Stage 3; the current demo uses a manual trigger, same as the weekly digest.

For Sarah, 400 miles away, Alexa surfaces mood trends, confusion signals, and which memories Frank has been reaching for — without a phone call, without Frank having to explain. A weekly digest summarizes the week in plain language: how he's been, what he's talked about, one thing worth adding.

No app. No screen. Both Frank and his family interact entirely through Alexa — just voice, memory, and the people who matter. No training required.

Demo note: The hackathon prototype includes a web UI that simulates both Frank's view and the family view in one place — so judges can exercise the full system without a physical Alexa device. In the real product, both roles are voice-native through Alexa+.


How I built it

Folkore is a TypeScript MCP server built to spec 2025-11-25 using Streamable HTTP transport, exposing two tools to Alexa+:

  • converse — the single entry point for all utterances. Alexa+ calls this for every turn — parent or family. The Supervisor inside classifies intent and routes to the right specialist agent automatically.
  • morning_memory — surfaces an unprompted memory from the parent's personal graph each morning; Alexa calls this on a schedule to start Frank's day with something meaningful before he says a word.

Every request passes through a Supervisor that classifies intent — a single lightweight LLM call with no tools — and routes to one of three specialist agents, each running a real agentic tool-use loop where the LLM decides which tools to call and in which order. Parent utterances bypass classification entirely and route directly to the Conversation Agent.

Four agents:

  • Supervisor — classifies every utterance and routes to the right specialist. No business logic lives here.
  • Conversation Agent — parent-facing. Runs hybrid three-layer retrieval, responds warmly. Confusion detection runs server-side via a dedicated LLM classifier (temperature: 0) in parallel with the agent — zero added latency, catches indirect signals regex misses.
  • Curation Agent — family-facing. Validates memory completeness, stores to DynamoDB and S3, extracts named entities into the graph, confirms back to the family.
  • Insight Agent — generates mood trends, confusion narratives, and the weekly digest email from live interaction data.

Memory graph schema: Nodes are typed (person, place, event); edges are typed (subject_of) connecting nodes to the memories about them. This is what makes "tell me about Marcus" resolve to three specific memories through a two-hop traversal before keyword search runs.

Three-layer hybrid retrieval:

  1. Graph traversal — named entity match → follow edges → collect memory IDs instantly
  2. DynamoDB keyword scoring — always fresh, catches memories added seconds ago
  3. Bedrock Knowledge Base — semantic vector search, best-effort augmentation

AWS stack: DynamoDB (6 tables), S3, Amazon Bedrock Knowledge Base, Bedrock Agent for KB sync management, Bedrock Mantle gateway for LLM inference via deepseek.v3.2.

Guaranteed logging: logInteraction runs unconditionally in the server wrapper after every turn — not as a tool call the LLM might skip. Logging persists even if the agent errors, hits max iterations, or returns an empty response. The insight dashboard's data is always complete.

Guardrails: PII scrubbing strips phone numbers, emails, SSNs, and card numbers from all memory fields before any write. Rate limiting at 20 req/min per IP prevents runaway spend.

Deployment: The server runs on AWS Lambda with a Function URL — a persistent public HTTPS endpoint judges can connect Alexa+ to directly, with no local setup required. The Lambda bundle is a single index.mjs produced by esbuild, excluding the AWS SDK (available in the Lambda runtime), keeping the zip small and startup fast.

System prompts live in .txt files — version-controlled, diffable, readable without TypeScript. A clinician reviewing what Folkore says to a dementia patient can open a text file and read it. Changing a prompt never requires a code deploy.


Challenges I ran into

Getting retrieval right. A single query — "tell me about my grandson" — needs to find memories stored under different words, different tags, or linked through a graph relationship. Pure keyword search misses semantic distance. Pure vector search misses freshness. I built a three-layer pipeline that merges all three: graph traversal for entity-centric queries, DynamoDB for always-fresh results, Bedrock KB for semantic augmentation. The graph layer was the key unlock — "Marcus" resolves to a node, the node resolves to every memory about Marcus, before keyword scoring even runs.

KB sync concurrency. Bedrock KB ingestion is asynchronous. If a family adds two memories in quick succession, a naive implementation fires two StartIngestionJob calls and one hits ConflictException. I built a sync guard that checks ListIngestionJobs before every fire — if a job is already running, the file is already in S3 and will be picked up incrementally. DynamoDB keyword retrieval always covers freshness regardless of KB sync state.

PII in unexpected places. Families dictate contact details alongside memories — "Sarah's number is 555-..." — and phone numbers contain enough digits to trigger PII scrubbers unexpectedly. Even our own eval test markers (timestamp-based strings with long digit runs) hit the scrubber during testing. I tightened the scrubbing regex and switched all internal markers to alphanumeric-only strings.

Making retrieval merge correctly. Three layers returning results independently isn't enough — they need to merge, deduplicate, and agree on what to surface. The final pipeline deduplicates by memory_id across all three layers, updates last_referenced and reference_count on every hit so the Insight Agent knows which memories Frank reaches for most, and returns a ranked list the agent can reason about. Getting that merge to be both correct and fast — graph traversal completes in milliseconds; KB can lag — required careful ordering: graph and DynamoDB always run, KB augments on top.

Keeping the demo honest about SNS. We wanted to show the weekly digest but didn't have time to wire EventBridge + SNS. Rather than hide the gap, we built a manual trigger and a clear UI badge: "Manual trigger · SNS delivery in Stage 3." The email is real — generated from Frank's actual data. The delivery mechanism is the staged part.


Accomplishments that I'm proud of

20/20 behavioral evals passing against live AWS. Five suites — tone, retrieval correctness, confusion detection, hallucination guard, and curation write/read — all passing against the real DynamoDB and Bedrock stack. No mocks. No LLM-as-judge. Pure string and regex assertions against deterministic system behavior. The hallucination guard in particular verifies that the Conversation Agent only names people and places that exist in Frank's actual memory graph — it never invents a relative, a place, or a story.

LLM confusion detection, zero added latency. The classifier runs in parallel — Promise.all — so it never delays Frank's response. It catches indirect signals ("What year did I retire?" when the real question is "what year is it?") that a regex would miss entirely. Every confusion event is a typed enum in the log, not a boolean flag — the family sees what kind of confusion, not just that it happened.

Prompts as first-class artifacts. Every agent's system prompt lives in a .txt file. Changing what Folkore says to a dementia patient is a file edit, not a code deploy. That's the kind of auditability a product like this needs in production.

Guaranteed logging. No matter what the agent does — errors, hits max iterations, returns empty — logInteraction fires. The insight dashboard is never missing a day.

90 unit tests with zero AWS dependencies. Confusion detection, agent loop behavior, PII scrubbing, rate limiting, and keyword scoring — all testable locally with no cloud setup.


What I learned

The hardest problem in a memory companion isn't storage — it's retrieval. Getting the right memory at the right moment, for a query the family didn't anticipate when they wrote it, is where naive approaches break down. The memory graph was the architectural decision that unlocked entity-centric retrieval: once "Marcus" is a node, every memory about Marcus is reachable through a two-hop traversal regardless of how the family worded it.

We also learned that honesty about staged features is better than hiding gaps. The weekly digest manual trigger and the "SNS in Stage 3" badge are more compelling to a judge than a faked automation. The email is real. The data is real. The trigger mechanism is the thing that's staged — and saying so explicitly is more trustworthy than pretending.

Targeted guardrails matter more than generic LLM-level safeguards for a product in this space. Confusion detection by a dedicated low-temperature classifier, PII scrubbing before every write, logging outside the agent loop — these aren't limitations, they're the right architecture for a system that touches vulnerable people.


What's next for Folkore

Stage 2 — Richer Memory

  • Multi-person households — support multiple parents under one family account, each with their own memory graph and confusion tracking
  • Voice-native curation — multi-turn memory intake where Alexa asks follow-up questions to fill gaps: "You said Sarah visited — when was that? Anything else about that visit worth remembering?"
  • Photo memories — when Alexa opens photo ingestion to MCP tools, a vision model extracts names and context from family photos into voice-retrievable memories
  • Memory aging — surface recently added memories more often; rotate older ones back in on anniversaries or relevant dates

Stage 3 — Proactive Family Intelligence

  • Real EventBridge trigger — morning memory fires automatically every day per registered parent
  • Automated SNS digest — weekly email fires every Sunday without manual trigger
  • Confusion escalation — spike in confusion rate triggers immediate family notification, not just the weekly cycle
  • Memory gap detection — Insight Agent flags entities Frank mentions that have no memory attached: "Frank mentioned 'the Hendersons' twice this week — no memory exists for them"

Stage 4 — Production & Privacy

  • Multi-tenant isolation — per-family DynamoDB partitions, per-family S3 prefixes
  • HIPAA-aligned storage — encryption at rest and in transit, audit log of every memory access
  • Neptune migration — replace DynamoDB graph tables with Amazon Neptune for native multi-hop traversal as graphs grow past 500 nodes
  • Caregiver portal — read-only view for professional caregivers: confusion trends, memory coverage, conversation summaries — no raw transcript, ever

Built With

Share this project:

Updates

Submission history