Skip to content

Repository files navigation

Lavni Internal Scheduling Assistant

Working prototype of an internal scheduling assistant for Lavni admin/support. It reviews mock RingCentral, Twilio, and therapist/client chat data, extracts scheduling intent, checks availability/conflicts, schedules only when safe, and uses a mock Slack channel for notifications and approvals.

This is not a client-facing bot. It never messages clients or takes over conversations.

Stack

  • Backend: Python FastAPI (backend/)
  • Frontend: React + Vite (client/)
  • Data: JSON mock files under data/ (default)
  • Integrations: Provider adapters (mock today → live APIs when keys are set)
  • NLP: Mock AI layer by default (rule-based). Optional OpenAI/Anthropic when USE_LLM=true + API key.

Mock vs live providers

By default no API keys are required. Copy .env.example.env only when you want to enable live channels or LLM NLP.

Env Meaning
USE_MOCK=true Force all channel providers to local JSON (interview default)
USE_LLM=false Mock AI layer for intent/entities (default). Set true + OPENAI_API_KEY or ANTHROPIC_API_KEY to use an LLM
LIVE_SLACK=true Use live Slack provider (needs SLACK_BOT_TOKEN)
LIVE_RINGCENTRAL=true Live RingCentral conversations
LIVE_TWILIO=true Live Twilio messages
LIVE_THERAPIST_CHAT=true Live Lavni chat API
LIVE_CALENDAR=true Live calendar / Lavni scheduling API

Orchestrator code talks to interfaces in backend/app/providers/ and NLP via backend/app/agent/nlp.py. Mock implementations read data/; live/LLM stubs activate when keys are set. Check GET /api/healthproviders.nlp.

CLI testing (no UI)

With the venv active, from the project root (or use npm run cli -- …):

.venv/bin/python -m backend.app.cli health
.venv/bin/python -m backend.app.cli reset
.venv/bin/python -m backend.app.cli ask ""
.venv/bin/python -m backend.app.cli slack
.venv/bin/python -m backend.app.cli appointments
.venv/bin/python -m backend.app.cli approve slack_1 --alt 0
.venv/bin/python -m backend.app.cli reject slack_1 --note "Need follow-up"
.venv/bin/python -m backend.app.cli demo              # all cases, reset between each
.venv/bin/python -m backend.app.cli demo --pause
.venv/bin/python -m backend.app.cli demo --only 2

One-by-one CLI demo (copy/paste)

Always start with health + reset. Use slack after conflict/cancel to see the approval id (slack_1, slack_2, …).

# 0) Status + clean state
.venv/bin/python -m backend.app.cli health
.venv/bin/python -m backend.app.cli reset

# 1) Clear schedule → expect schedule + Slack notification
.venv/bin/python -m backend.app.cli ask "Schedule John Smith with Carol next Tuesday at 2 PM."
.venv/bin/python -m backend.app.cli slack
.venv/bin/python -m backend.app.cli appointments

# 2) Calendar conflict → expect therapist_conflict + pending approval
.venv/bin/python -m backend.app.cli reset
.venv/bin/python -m backend.app.cli ask "Schedule Jane Doe with Carol on July 28, 2026 at 2 PM."
.venv/bin/python -m backend.app.cli slack
# 2b) Approve first alternative (0 = 9:00 AM) — do NOT use plain approve (2 PM still conflicted)
.venv/bin/python -m backend.app.cli approve slack_1 --alt 0

# 3) Ambiguous → escalate; then reject
.venv/bin/python -m backend.app.cli reset
.venv/bin/python -m backend.app.cli ask "Schedule Chris with someone tomorrow morning."
.venv/bin/python -m backend.app.cli slack
.venv/bin/python -m backend.app.cli reject slack_1 --note "Reject - client needs follow-up first"

# 4) Duplicate prevention
.venv/bin/python -m backend.app.cli reset
.venv/bin/python -m backend.app.cli ask "Jane Doe confirmed her appointment with Carol Tuesday at 10 — please schedule it."

# 5) Cancel → approval (approve or reject)
.venv/bin/python -m backend.app.cli reset
.venv/bin/python -m backend.app.cli ask "Cancel Maria Garcia appointment with David."
.venv/bin/python -m backend.app.cli slack
# Approve cancel:
.venv/bin/python -m backend.app.cli approve slack_1
# Or reject cancel:
# .venv/bin/python -m backend.app.cli reject slack_1 --note "Need follow-up first"

# 6) RingCentral scan → findings only, no auto-book
.venv/bin/python -m backend.app.cli reset
.venv/bin/python -m backend.app.cli ask "Go through my RingCentral conversations from July 20 and find anyone who needs an appointment."

# 6b) Twilio + therapist chat scan
.venv/bin/python -m backend.app.cli reset
.venv/bin/python -m backend.app.cli ask "Review today's Twilio messages and therapist-client chats and tell me who may need scheduling help."

# 7) Reserved blocked slot → calendar_blocked
.venv/bin/python -m backend.app.cli reset
.venv/bin/python -m backend.app.cli ask "Schedule John Smith with Carol on July 28, 2026 at 4 PM."
.venv/bin/python -m backend.app.cli slack

You can also hit the HTTP API with curl while npm run dev is running (see OpenAPI at /docs).

Quick start

# 1) Python deps (venv)
python3 -m venv .venv
source .venv/bin/activate   # Windows: .venv\Scripts\activate
pip install -r requirements.txt

# 2) Frontend deps
npm install

# 3) Run API + UI together
npm run dev

Or run separately:

npm run server   # FastAPI on :8000
npm run client   # Vite on :5173

What the assistant does

  1. Accepts admin prompts in the left/center chat
  2. Classifies the request (direct schedule / scan / ambiguous)
  3. Looks up clients & therapists from mock records
  4. Checks working hours, blocked slots, conflicts, duplicates
  5. Auto-schedules only when safe; otherwise posts a Slack approval card
  6. On successful schedule, posts a Slack notification to #lavni-admin-scheduling

Demo clock

By default, relative dates use a fixed demo “now” aligned with seed mock data:

Tuesday, July 28, 2026, 9:00 AM ET

So “next Tuesday at 2 PM” resolves to August 4, 2026 at 2:00 PM ET.

Optional: set USE_REAL_CLOCK=true in .env to use the current America/New_York time instead. If you do that, update mock appointment / conversation dates and demo prompts so they still line up. The UI pill shows Demo clock: … or Now: … from GET /api/health.

Seed calendar highlights (July 28)

Slot Why
Carol 10:00 AM Jane Doe existing appointment (duplicate demo)
Carol 2:00 PM Alex Rivera booked (conflict demo)
Carol 4:00–5:00 PM Reserved blocked slot — cannot auto-book
Carol all day July 29 PTO block
David 10:00 AM July 30 Maria Garcia (cancel/reschedule demo)

Demo prompts (required scenarios)

Use the buttons in the UI, or send these via chat:

# Prompt Expected
1 Schedule John Smith with Carol next Tuesday at 2 PM. Schedules + Slack notification
2 Schedule Jane Doe with Carol on July 28, 2026 at 2 PM. Conflict → Slack approval + alternatives
3 Schedule Chris with someone tomorrow morning. Ambiguous → escalate
4 Jane Doe confirmed her appointment with Carol Tuesday at 10 — please schedule it. Duplicate prevented
5 Cancel Maria Garcia appointment with David. Cancel requires Slack approval
6 Go through my RingCentral conversations from July 20 and find anyone who needs an appointment. Findings list; no auto-schedule
7 Schedule John Smith with Carol on July 28, 2026 at 4 PM. Reserved block → no auto-book

Also: Review today's Twilio messages and therapist-client chats and tell me who may need scheduling help.

Use Reset demo between walkthroughs.

Human approval rules

May schedule directly only when:

  • Admin explicitly asks to schedule/book
  • Client and therapist are uniquely identified
  • Date/time are clear
  • Therapist is available (working hours, not blocked)
  • No therapist/client conflict
  • No duplicate appointment

Requires admin approval when:

  • Ambiguous client/therapist (e.g. multiple “Chris”)
  • Missing/unclear date or time
  • Calendar conflict or blocked slot
  • Client not assigned to requested therapist
  • Reschedule or cancellation
  • Findings from conversation scans
  • Low-confidence / unclear intent

Slack simulation

No real Slack workspace is connected. The right panel is #lavni-admin-scheduling.

  • Notifications after every successful schedule (direct or after approval)
  • Approval cards with Approve requested / Approve alt N / Reject / Schedule custom time

Approvals call POST /api/slack/approvals/{id}.

How the assistant avoids taking over client conversations

  • It only responds to admin chat in this internal UI
  • Mock RingCentral / Twilio / therapist chat are read-only inputs
  • There is no outbound client messaging channel in the prototype

Assumptions

  • Session length is 1 hour
  • Timezone display/storage uses ET (-04:00) for July demo data
  • Therapist workingDays use JS-style weekday numbers (0=Sun … 6=Sat)
  • Intent detection uses the mock AI layer by default (USE_LLM=false). Set USE_LLM=true and add OPENAI_API_KEY or ANTHROPIC_API_KEY to switch NLP to an LLM (policy/calendar stay local).
  • Seed appointments live in data/appointments.json; runtime writes go to data/runtime/state.json

API surface

Method Path Purpose
POST /api/agent/message Admin prompt → agent result
GET /api/slack/messages Mock Slack feed
POST /api/slack/approvals/{id} Approve / reject / custom time
GET /api/appointments Current appointments
POST /api/reset Reset runtime state
GET /api/health Health check

Project layout

backend/app/          FastAPI app, agent, services, routers
client/               React admin UI
data/                 Seed mock data + runtime state
ARCHITECTURE.md       Design notes

What I’d improve with more time

  • Swap deterministic NLP for an LLM with structured output + confidence scores
  • Real RingCentral / Twilio / Lavni chat / Google or Outlook calendar / Slack APIs
  • AuthN/AuthZ, audit export, PHI encryption at rest
  • Multi-timezone scheduling and “same time as last week”
  • Stronger duplicate detection across nearby times / telehealth links
  • Automated test suite for all policy branches

See ARCHITECTURE.md for data flow, safety, HIPAA notes, and production integration path.

About

test-task

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages