Inspiration

I'm a CS student, not a healthcare professional — but this project came from watching how easily critical information falls through the cracks when people are overloaded. A care coordinator managing dozens or hundreds of patients cannot manually cross-reference every medication against every condition, every referral against every deadline, every single day. That's not a hypothetical gap — preventable medication errors and missed follow-up care are a documented, ongoing cause of patient harm. I wanted to see if an AI agent could actually close that gap, not just talk about it.

I also wanted the agent to live somewhere care teams already work. Slack made sense — it's already the coordination layer for a lot of healthcare operations teams, so instead of asking anyone to adopt a new tool, CareNav just becomes part of the conversation they're already having.

What it does

CareNav is an autonomous Slack agent that:

  • Scans an entire patient panel in one command and flags who needs attention
  • Deep-analyzes individual patients using a genuine agent loop — Claude decides which tools to call (fetch patient record, check drug interactions, check overdue referrals) and in what order, without a hardcoded script
  • Flags dangerous drug-condition and drug-drug interactions sourced directly from real FDA drug safety labeling (not invented data) — for example, it correctly applies the FDA's 2016 metformin/CKD staging thresholds, distinguishing between CKD Stage 3a (safe), 3b (caution, dose cap), and Stage 4 (contraindicated)
  • Understands plain English updates — a care coordinator can just tell it "we spoke to the doctor, Metformin's been stopped" and CareNav extracts the structured update, shows exactly what it understood, and waits for explicit human confirmation before touching any patient record
  • Automatically re-analyzes a patient after any update, so the care plan is always current
  • Pulls in relevant team context automatically via Slack's Real-Time Search API — before the agent even starts reasoning, it searches the workspace for anything relevant to the patient being discussed
  • Logs every single action to an append-only audit trail — who changed what, when, and how — because that kind of accountability is non-negotiable before a tool like this could be trusted anywhere near real patient care

How I built it

  • Slack Bolt SDK (Node.js) as the interface layer — slash commands, @mention natural language handling, and interactive Block Kit buttons
  • Claude's tool-use API as the reasoning engine. I defined four tools (get_patient, check_interactions, check_referrals, save_care_plan) and let Claude decide the calling sequence itself, based on what each result told it
  • A separate Claude call for intent extraction — a smaller, more constrained model call that reads a natural-language Slack message and returns structured JSON describing what changed, before anything gets confirmed or written
  • MongoDB Atlas for patient records, an FDA-sourced drug interaction rules collection, and a separate append-only care_records collection for the audit log
  • Slack's Real-Time Search API to pull in relevant workspace context before the agent begins reasoning, so it's aware of what the team has already discussed
  • Block Kit for the actual care plan UI — structured cards instead of a wall of markdown text, with interactive buttons for viewing the full patient record or the full change history

Challenges I ran into

The hardest bug wasn't visible in the UI at all — it was a data integrity issue. Early on, I had Claude's tool calls pass medication data as plain strings extracted from what it had read in the patient record. It worked most of the time, but I eventually caught Claude silently flattening structured medication objects ({name, status}) into bare strings when constructing tool calls — which meant a medication's discontinued status could get lost in transit, and the agent would keep flagging a drug that had already been stopped. The fix was architectural: tools should never trust data relayed through the LLM. I rewrote every tool to query MongoDB directly by patient name instead of accepting patient data as an argument, so the database is always the single source of truth, and Claude only ever reasons over freshly-fetched data.

I also had to get genuinely careful with the clinical data itself. My first pass at the drug interaction rules was written from memory and included at least one real error — I had metformin flagged as contraindicated in CKD Stage 3 broadly, when the FDA's actual 2016 label revision only contraindicates it below eGFR 30 (Stage 4-5), with Stage 3b requiring caution and dose capping rather than an outright block. I went back and rebuilt the entire interaction dataset against actual FDA drug labeling and safety communications, which is also why the demo specifically shows the agent getting the CKD staging nuance right — it's not a coincidence, it's the whole point.

What I learned

Building an agent that's trustworthy is a different problem than building an agent that's impressive in a demo. The features that took the least time to build — the audit log, the human-in-the-loop confirmation step before any write — ended up being the features that actually mattered most for a healthcare context. It's easy to make an agent that acts autonomously and looks smart doing it. It's much harder, and more important, to build one that acts autonomously in a way a real care team could actually trust.

Built With

Share this project:

Updates