CareCompass — AWS Agents for Humans (Good Neighbor Agents)

Repo: https://github.com/fab679/carecompass · Demo video: (link in the Devpost form)

Inspiration

Not long ago I needed a hospital with a NICU. Nobody could tell me which one nearby actually had a cot free that night, so I did what everyone does: I went to the nearest hospital, was sent on to the next, and then the next. I never got the help I was looking for. I was lucky — it turned out to be a false alarm. But I kept thinking about the family for whom it isn't.

That is the problem in Nyeri County, and in most places. "Go to the nearest hospital" can be the wrong advice. The nearest facility may have no CT scanner working today, no antivenom in stock, no newborn cot free. What each facility can treat right now changes constantly, and keeping that knowledge current — re-verifying scanners, stock and wards — is endless, repetitive work that nobody has time for. So it doesn't get done, and people like me are routed on stale assumptions in the minutes that decide outcomes.

I wanted an agent that does that tedious work quietly for a whole community, and speaks up at exactly two moments: when a person must decide, and when a person needs to know where to go. In the demo, the county referral hospital's NICU is marked full — and the guide says so before you set off.

What it does

Two halves share one living knowledge graph of the county's facilities.

Facility Intelligence — autonomous, in the background. On a schedule (or "Run now"), a Strands Graph of four Nova 2 Lite agents finds capabilities and ward statuses nobody has confirmed within policy, sends each facility one short verification message, reads their free-text replies ("CT is down until Friday", "antivenom yes we have"), and compares them with what the graph believes. A deterministic dispositor then decides: confident confirmations and low-risk changes are applied automatically with provenance; anything with low confidence, a source conflict, or that would remove a time-critical capability becomes a single decision for a human coordinator, with the evidence quoted and the reason stated. That inbox is the only time anyone is asked to do anything.

Voice Guide — real time. A caller taps one button and talks (or types). A Strands BidiAgent on Amazon Nova 2 Sonic listens, and tool code — not the model — decides whether this is a red-flag emergency; if so the first thing it says is "call 922". It resolves where the caller is from a landmark ("we're at the stage"), finds the nearest facility that satisfies every care requirement of the likely condition, ranks the shortlist by real road time from Amazon Location, and reads out the emergency-entrance directions. The card appears on screen with a map link. Callers can interrupt, type instead of speaking, and describe symptoms in Swahili.

Facility staff mark a ward Full in one tap (or type "icu 1 bed, nicu full" for an agent to interpret); the next caller is told.

How I built it

  • Strands Agents SDK (Python 3.12): BidiAgent + Nova 2 Sonic for speech-to-speech with barge-in and async tool calls; a Graph with two parallel entry points (detect stale → request verification; interpret replies → reconcile) on Nova 2 Lite; tools that write structured proposals into invocation_state; a structured-output agent for staff free text.
  • Amazon Bedrock AgentCore: the voice guide is a BedrockAgentCoreApp WebSocket runtime; the background pipeline an HTTP /invocations runtime; a Graph MCP server exposes the same query module as Gateway-ready tools.
  • Neo4j AuraDB: conditions NEEDS care requirements, requirements are SATISFIED_BY capabilities, facilities PROVIDES_24_7 | PROVIDES_ON_CALL | PROVIDES_SCHEDULED | TEMPORARILY_UNAVAILABLE them; a point index for "near me"; Titan Text Embeddings V2 over English and Swahili aliases in a vector index; full-text as fallback; an append-only change history per capability.
  • Amazon Location Service: route matrices for road ETAs and geocoding with a service-area guard.
  • DynamoDB for decisions, verification requests, replies and the activity feed.
  • React + Vite PWA: AudioWorklet mic capture at 16 kHz, instant playback flush on interruption, live captions, a coordinator console with KPI strip, decision inbox and activity log, a MapLibre map, and a facility status page.
  • Safety is structural: escalation is a tool's return value; facility facts only come from tools; enums are generated from the graph vocabulary so the model cannot invent codes; verification messages are composed by code from validated items; LLMs only propose data changes; removing a time-critical capability always needs a human; stale status is announced, never hidden; no audio, transcripts or coordinates are stored.

Challenges I ran into

  • Nova Sonic only takes turns while its audio stream is open. Text-only sessions silently produced nothing until I found this; the server now feeds silence for callers without a microphone, which also made the typed fallback work.
  • False escalations. The first vector-similarity floor let "mild headache since yesterday" match stroke aliases; I calibrated the threshold on real Titan scores (hits ≥ 0.69, noise ≤ 0.62 → floor 0.66). The full-text fallback had the same problem and now re-scores by token overlap.
  • Agents that guess. In a multi-agent Graph the next agent only sees the previous one's text summary; ours guessed facility ids and even wrote invented capability names into messages. I gave each agent a tool that returns the exact structured items from shared state, and moved message composition into code.
  • Geocoding that "helps" too much. A vague landmark once resolved to a flower market in Amsterdam; place hits are rejected outside a 150 km service area, and prefix stemming is off for place names after "Kenyatta" matched "Kenya".
  • Phones. Switching apps drops the WebSocket; browsers only grant the microphone from a tap. The reconnect keeps the mic stream alive and resumes with the same session id.

Accomplishments that I'm proud of

  • One complete loop, all live: a stale record → agents verify → a CT outage is escalated with evidence → a coordinator taps Approve → the next stroke caller is routed past the closest hospital to the one that can treat them, by road time, to the right gate.
  • 48 automated tests, most against the live graph, including the whole verification loop offline and a table-driven suite for the dispositor — the code that decides what may never be automated.
  • Real geography: 12 real Nyeri facilities and 20 real landmarks, so "I'm at the stage" just works — and it understands Swahili.

What I learned

"Nearest" is the wrong question; "nearest capable, right now" is the right one — and that is a graph question. Voice agents want few tools, enum arguments and a pre-written say field. In multi-agent pipelines, hand structured state between agents through tools, not prose. And the safest agent design puts the LLM where it is good (reading messy replies, holding a calm conversation) and keeps every irreversible decision in code you can unit-test.

What's next for carecompass

  • Phone-call access (Nova 2 Sonic telephony) for people without smartphones or data, and USSD/SMS for status updates where data is unreliable.
  • AgentCore Gateway with Cedar policies separating read and write tools; Cognito for staff and coordinators; Amplify hosting for a public live demo.
  • Clinically reviewed symptom mappings and pre-arrival guidance with local emergency-medicine partners; native-speaker review of the Swahili aliases.
  • Onboarding real facilities with the Nyeri County Department of Health.

Facility names and locations are real (Nyeri County, Kenya); capabilities, bed status, entrances and staff are synthetic demo data. Clinical mappings are illustrative. CareCompass gives directions, not diagnosis. Emergency numbers shown (922, 999, 112) are Kenya's real lines.

Built With

Share this project:

Updates

Submission history