empathy-framework 3.5.6__py3-none-any.whl → 3.7.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. agents/compliance_anticipation_agent.py +113 -118
  2. agents/compliance_db.py +339 -0
  3. agents/epic_integration_wizard.py +37 -48
  4. agents/notifications.py +291 -0
  5. agents/trust_building_behaviors.py +66 -85
  6. coach_wizards/__init__.py +11 -12
  7. coach_wizards/accessibility_wizard.py +12 -12
  8. coach_wizards/api_wizard.py +12 -12
  9. coach_wizards/base_wizard.py +26 -20
  10. coach_wizards/cicd_wizard.py +15 -13
  11. coach_wizards/compliance_wizard.py +12 -12
  12. coach_wizards/database_wizard.py +12 -12
  13. coach_wizards/debugging_wizard.py +12 -12
  14. coach_wizards/documentation_wizard.py +12 -12
  15. coach_wizards/generate_wizards.py +1 -2
  16. coach_wizards/localization_wizard.py +21 -14
  17. coach_wizards/migration_wizard.py +12 -12
  18. coach_wizards/monitoring_wizard.py +12 -12
  19. coach_wizards/observability_wizard.py +12 -12
  20. coach_wizards/performance_wizard.py +12 -12
  21. coach_wizards/prompt_engineering_wizard.py +22 -25
  22. coach_wizards/refactoring_wizard.py +12 -12
  23. coach_wizards/scaling_wizard.py +12 -12
  24. coach_wizards/security_wizard.py +12 -12
  25. coach_wizards/testing_wizard.py +12 -12
  26. {empathy_framework-3.5.6.dist-info → empathy_framework-3.7.0.dist-info}/METADATA +234 -30
  27. empathy_framework-3.7.0.dist-info/RECORD +105 -0
  28. empathy_healthcare_plugin/__init__.py +1 -2
  29. empathy_llm_toolkit/__init__.py +5 -6
  30. empathy_llm_toolkit/claude_memory.py +14 -15
  31. empathy_llm_toolkit/code_health.py +27 -19
  32. empathy_llm_toolkit/contextual_patterns.py +11 -12
  33. empathy_llm_toolkit/core.py +43 -49
  34. empathy_llm_toolkit/git_pattern_extractor.py +16 -12
  35. empathy_llm_toolkit/levels.py +6 -13
  36. empathy_llm_toolkit/pattern_confidence.py +14 -18
  37. empathy_llm_toolkit/pattern_resolver.py +10 -12
  38. empathy_llm_toolkit/pattern_summary.py +13 -11
  39. empathy_llm_toolkit/providers.py +27 -38
  40. empathy_llm_toolkit/session_status.py +18 -20
  41. empathy_llm_toolkit/state.py +20 -21
  42. empathy_os/__init__.py +72 -73
  43. empathy_os/cli.py +193 -98
  44. empathy_os/cli_unified.py +68 -41
  45. empathy_os/config.py +31 -31
  46. empathy_os/coordination.py +48 -54
  47. empathy_os/core.py +90 -99
  48. empathy_os/cost_tracker.py +20 -23
  49. empathy_os/discovery.py +9 -11
  50. empathy_os/emergence.py +20 -21
  51. empathy_os/exceptions.py +18 -30
  52. empathy_os/feedback_loops.py +27 -30
  53. empathy_os/levels.py +31 -34
  54. empathy_os/leverage_points.py +27 -28
  55. empathy_os/logging_config.py +11 -12
  56. empathy_os/monitoring.py +27 -27
  57. empathy_os/pattern_library.py +29 -28
  58. empathy_os/persistence.py +30 -34
  59. empathy_os/platform_utils.py +46 -47
  60. empathy_os/redis_config.py +14 -15
  61. empathy_os/redis_memory.py +53 -56
  62. empathy_os/templates.py +12 -11
  63. empathy_os/trust_building.py +44 -36
  64. empathy_os/workflow_commands.py +123 -31
  65. empathy_software_plugin/__init__.py +1 -2
  66. empathy_software_plugin/cli.py +32 -25
  67. empathy_software_plugin/plugin.py +4 -8
  68. empathy_framework-3.5.6.dist-info/RECORD +0 -103
  69. {empathy_framework-3.5.6.dist-info → empathy_framework-3.7.0.dist-info}/WHEEL +0 -0
  70. {empathy_framework-3.5.6.dist-info → empathy_framework-3.7.0.dist-info}/entry_points.txt +0 -0
  71. {empathy_framework-3.5.6.dist-info → empathy_framework-3.7.0.dist-info}/licenses/LICENSE +0 -0
  72. {empathy_framework-3.5.6.dist-info → empathy_framework-3.7.0.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,4 @@
1
- """
2
- Compliance Anticipation Agent - Level 4 Anticipatory Empathy
1
+ """Compliance Anticipation Agent - Level 4 Anticipatory Empathy
3
2
 
4
3
  Multi-step LangGraph agent that predicts regulatory audits, identifies compliance
5
4
  gaps, and prepares documentation proactively to achieve positive outcomes.
@@ -33,8 +32,7 @@ logger = logging.getLogger(__name__)
33
32
 
34
33
 
35
34
  class ComplianceAgentState(TypedDict):
36
- """
37
- Level 4 Anticipatory Agent State
35
+ """Level 4 Anticipatory Agent State
38
36
 
39
37
  Follows Principle #13: "Agent State as Clinical Flowsheet"
40
38
  Every field answers a compliance question with clear audit trail.
@@ -195,10 +193,10 @@ class ComplianceAgentState(TypedDict):
195
193
 
196
194
 
197
195
  def create_initial_state(
198
- hospital_id: str, audit_type: str = "joint_commission"
196
+ hospital_id: str,
197
+ audit_type: str = "joint_commission",
199
198
  ) -> ComplianceAgentState:
200
- """
201
- Create initial agent state
199
+ """Create initial agent state
202
200
 
203
201
  Args:
204
202
  hospital_id: Unique identifier for hospital/facility
@@ -206,6 +204,7 @@ def create_initial_state(
206
204
 
207
205
  Returns:
208
206
  Initialized ComplianceAgentState
207
+
209
208
  """
210
209
  now = datetime.now()
211
210
  execution_id = f"compliance_{now.strftime('%Y%m%d_%H%M%S')}_{hospital_id}"
@@ -281,8 +280,7 @@ def create_initial_state(
281
280
 
282
281
 
283
282
  def create_compliance_agent() -> StateGraph:
284
- """
285
- Create Level 4 Anticipatory Compliance Agent
283
+ """Create Level 4 Anticipatory Compliance Agent
286
284
 
287
285
  Workflow:
288
286
  1. Predict Audit Timeline → When will next audit occur?
@@ -299,7 +297,6 @@ def create_compliance_agent() -> StateGraph:
299
297
  - Actionable (assigns specific tasks with deadlines)
300
298
  - Transparent (explains reasoning, provides confidence scores)
301
299
  """
302
-
303
300
  workflow = StateGraph(ComplianceAgentState)
304
301
 
305
302
  # Step 1: Audit Prediction
@@ -350,8 +347,7 @@ def create_compliance_agent() -> StateGraph:
350
347
 
351
348
 
352
349
  def predict_next_audit(state: ComplianceAgentState) -> ComplianceAgentState:
353
- """
354
- Step 1: Predict when next audit will occur
350
+ """Step 1: Predict when next audit will occur
355
351
 
356
352
  Methods (in order of preference):
357
353
  1. Regulatory schedule (published audit windows) - confidence: 0.95
@@ -364,7 +360,6 @@ def predict_next_audit(state: ComplianceAgentState) -> ComplianceAgentState:
364
360
  - Reduces stress and scrambling
365
361
  - Allows time to fix gaps without pressure
366
362
  """
367
-
368
363
  logger.info(f"[Step 1] Predicting {state['audit_type']} audit for {state['hospital_id']}")
369
364
 
370
365
  # Add to audit trail
@@ -375,7 +370,7 @@ def predict_next_audit(state: ComplianceAgentState) -> ComplianceAgentState:
375
370
  "action": "Starting audit prediction",
376
371
  "details": {"audit_type": state["audit_type"]},
377
372
  "user": "system",
378
- }
373
+ },
379
374
  )
380
375
 
381
376
  # Get audit cycle for this type
@@ -389,8 +384,10 @@ def predict_next_audit(state: ComplianceAgentState) -> ComplianceAgentState:
389
384
  cycle_months = audit_cycles.get(state["audit_type"], 36)
390
385
  state["audit_cycle_months"] = cycle_months
391
386
 
392
- # TODO: Connect to real database to get last audit date
393
- # For now, simulate with example date
387
+ # TODO: Integration point - Connect to real compliance database
388
+ # IMPLEMENTATION AVAILABLE: See agents/compliance_db.py ComplianceDatabase class
389
+ # Use: compliance_db.get_last_audit(audit_type=state["audit_type"])
390
+ # For now, this example uses simulated data to demonstrate the workflow
394
391
  # last_audit = get_last_audit_date(state["hospital_id"], state["audit_type"])
395
392
 
396
393
  # Example: Last Joint Commission audit was 2023-04-15
@@ -426,15 +423,15 @@ def predict_next_audit(state: ComplianceAgentState) -> ComplianceAgentState:
426
423
  # Log prediction
427
424
  logger.info(
428
425
  f"Predicted audit: {predicted_date.strftime('%Y-%m-%d')} "
429
- f"({days_until} days away, {confidence:.0%} confidence)"
426
+ f"({days_until} days away, {confidence:.0%} confidence)",
430
427
  )
431
428
 
432
429
  # Add message
433
430
  state["messages"].append(
434
431
  AIMessage(
435
432
  content=f"Predicted {state['audit_type']} audit on {predicted_date.strftime('%Y-%m-%d')} "
436
- f"(in {days_until} days) with {confidence:.0%} confidence"
437
- )
433
+ f"(in {days_until} days) with {confidence:.0%} confidence",
434
+ ),
438
435
  )
439
436
 
440
437
  # Audit trail
@@ -450,15 +447,14 @@ def predict_next_audit(state: ComplianceAgentState) -> ComplianceAgentState:
450
447
  "method": "historical_cycle",
451
448
  },
452
449
  "user": "system",
453
- }
450
+ },
454
451
  )
455
452
 
456
453
  return state
457
454
 
458
455
 
459
456
  def check_anticipation_window(state: ComplianceAgentState) -> ComplianceAgentState:
460
- """
461
- Step 2: Check if we're within optimal anticipation window
457
+ """Step 2: Check if we're within optimal anticipation window
462
458
 
463
459
  Level 4 Guardrail:
464
460
  - Too early (>120 days): Preparation may become outdated, waste effort
@@ -470,7 +466,6 @@ def check_anticipation_window(state: ComplianceAgentState) -> ComplianceAgentSta
470
466
  - Acting at right time maximizes effectiveness
471
467
  - Avoids wasted effort (too early) or crisis mode (too late)
472
468
  """
473
-
474
469
  logger.info(f"[Step 2] Checking anticipation window ({state['days_until_audit']} days)")
475
470
 
476
471
  days_until = state["days_until_audit"]
@@ -491,7 +486,7 @@ def check_anticipation_window(state: ComplianceAgentState) -> ComplianceAgentSta
491
486
  state["warnings"].append(
492
487
  f"Audit predicted in {days_until} days. "
493
488
  f"Optimal anticipation window is 60-120 days. "
494
- f"Will schedule re-check for {(datetime.now() + timedelta(days=days_until - 120)).strftime('%Y-%m-%d')}"
489
+ f"Will schedule re-check for {(datetime.now() + timedelta(days=days_until - 120)).strftime('%Y-%m-%d')}",
495
490
  )
496
491
 
497
492
  elif 30 <= days_until < 60:
@@ -502,7 +497,7 @@ def check_anticipation_window(state: ComplianceAgentState) -> ComplianceAgentSta
502
497
  state["warnings"].append(
503
498
  "Less than 60 days until audit. "
504
499
  "Limited time for comprehensive remediation. "
505
- "Recommend expedited action."
500
+ "Recommend expedited action.",
506
501
  )
507
502
 
508
503
  else: # < 30 days
@@ -512,7 +507,7 @@ def check_anticipation_window(state: ComplianceAgentState) -> ComplianceAgentSta
512
507
  message = f"🚨 URGENT: Only {days_until} days until audit. Focus on critical gaps only."
513
508
  state["warnings"].append(
514
509
  "Less than 30 days until audit. "
515
- "Very limited time. Focus on critical compliance gaps only."
510
+ "Very limited time. Focus on critical compliance gaps only.",
516
511
  )
517
512
 
518
513
  state["messages"].append(AIMessage(content=message))
@@ -532,7 +527,7 @@ def check_anticipation_window(state: ComplianceAgentState) -> ComplianceAgentSta
532
527
  "within_window": state["is_within_anticipation_window"],
533
528
  },
534
529
  "user": "system",
535
- }
530
+ },
536
531
  )
537
532
 
538
533
  logger.info(f"Anticipation window: {state['time_to_act']}")
@@ -541,28 +536,25 @@ def check_anticipation_window(state: ComplianceAgentState) -> ComplianceAgentSta
541
536
 
542
537
 
543
538
  def should_anticipate(state: ComplianceAgentState) -> str:
544
- """
545
- Routing function: Decide whether to proceed with anticipation
539
+ """Routing function: Decide whether to proceed with anticipation
546
540
 
547
541
  Returns:
548
542
  "anticipate" - Within optimal window, proceed
549
543
  "too_early" - Too far out, schedule for later
550
544
  "proceed_anyway" - Urgent, proceed despite non-optimal timing
551
- """
552
545
 
546
+ """
553
547
  time_to_act = state["time_to_act"]
554
548
 
555
549
  if time_to_act == "too_early":
556
550
  return "too_early"
557
- elif time_to_act in ["urgent", "too_late"]:
551
+ if time_to_act in ["urgent", "too_late"]:
558
552
  return "proceed_anyway"
559
- else:
560
- return "anticipate"
553
+ return "anticipate"
561
554
 
562
555
 
563
556
  def assess_current_compliance(state: ComplianceAgentState) -> ComplianceAgentState:
564
- """
565
- Step 3A: Assess current compliance status
557
+ """Step 3A: Assess current compliance status
566
558
 
567
559
  Scans all compliance requirements for the audit type and determines
568
560
  current compliance percentage.
@@ -572,11 +564,12 @@ def assess_current_compliance(state: ComplianceAgentState) -> ComplianceAgentSta
572
564
  - Categorization helps prioritize remediation
573
565
  - Baseline measurement enables tracking improvement
574
566
  """
575
-
576
567
  logger.info(f"[Step 3A] Assessing compliance for {state['audit_type']}")
577
568
 
578
- # TODO: Connect to real compliance data
579
- # For now, simulate assessment
569
+ # TODO: Integration point - Connect to real compliance assessment system
570
+ # IMPLEMENTATION AVAILABLE: See agents/compliance_db.py for status tracking
571
+ # Use: compliance_db.get_current_compliance_status(compliance_framework)
572
+ # For now, this example simulates assessment to demonstrate the workflow
580
573
 
581
574
  # Get requirements for this audit type
582
575
  requirements = get_audit_requirements(state["audit_type"])
@@ -591,7 +584,10 @@ def assess_current_compliance(state: ComplianceAgentState) -> ComplianceAgentSta
591
584
  category_scores = {}
592
585
 
593
586
  for req in requirements:
594
- # TODO: Check actual compliance
587
+ # TODO: Integration point - Check actual compliance against requirements
588
+ # IMPLEMENTATION AVAILABLE: Query from compliance_db.get_active_gaps()
589
+ # Filter gaps by framework and severity to determine compliance status
590
+ # For now, this example simulates compliance checks to demonstrate scoring logic
595
591
  # is_compliant = check_requirement_compliance(state["hospital_id"], req)
596
592
 
597
593
  # Simulated: 90% compliant
@@ -645,8 +641,8 @@ def assess_current_compliance(state: ComplianceAgentState) -> ComplianceAgentSta
645
641
  state["messages"].append(
646
642
  AIMessage(
647
643
  content=f"{status_emoji} Compliance Assessment: {compliance_pct:.1f}% "
648
- f"({compliant}/{total_items} items compliant)"
649
- )
644
+ f"({compliant}/{total_items} items compliant)",
645
+ ),
650
646
  )
651
647
 
652
648
  # Audit trail
@@ -662,7 +658,7 @@ def assess_current_compliance(state: ComplianceAgentState) -> ComplianceAgentSta
662
658
  "categories": category_pct,
663
659
  },
664
660
  "user": "system",
665
- }
661
+ },
666
662
  )
667
663
 
668
664
  logger.info(f"Compliance: {compliance_pct:.1f}% ({compliant}/{total_items})")
@@ -671,8 +667,7 @@ def assess_current_compliance(state: ComplianceAgentState) -> ComplianceAgentSta
671
667
 
672
668
 
673
669
  def identify_compliance_gaps(state: ComplianceAgentState) -> ComplianceAgentState:
674
- """
675
- Step 3B: Identify specific compliance gaps with actionable details
670
+ """Step 3B: Identify specific compliance gaps with actionable details
676
671
 
677
672
  For positive outcomes:
678
673
  - Specific patient IDs enable targeted remediation
@@ -680,11 +675,12 @@ def identify_compliance_gaps(state: ComplianceAgentState) -> ComplianceAgentStat
680
675
  - Time estimates enable resource planning
681
676
  - Retroactive fix capability determines urgency
682
677
  """
683
-
684
678
  logger.info("[Step 3B] Identifying compliance gaps")
685
679
 
686
- # TODO: Connect to real gap detection system
687
- # For now, simulate common gaps
680
+ # TODO: Integration point - Connect to real gap detection system
681
+ # IMPLEMENTATION AVAILABLE: See agents/compliance_db.py ComplianceDatabase.record_gap()
682
+ # Use: compliance_db.get_active_gaps(severity, framework) to retrieve detected gaps
683
+ # For now, this example simulates gap detection to demonstrate remediation planning
688
684
 
689
685
  gaps = []
690
686
  gap_id_counter = 1
@@ -710,7 +706,7 @@ def identify_compliance_gaps(state: ComplianceAgentState) -> ComplianceAgentStat
710
706
  "estimated_time_to_fix": "25 minutes",
711
707
  "can_fix_retroactively": True,
712
708
  "legal_risk": "medium",
713
- }
709
+ },
714
710
  )
715
711
  gap_id_counter += 1
716
712
 
@@ -729,7 +725,7 @@ def identify_compliance_gaps(state: ComplianceAgentState) -> ComplianceAgentStat
729
725
  "estimated_time_to_fix": "45 minutes",
730
726
  "can_fix_retroactively": False, # Can document review but can't undo administration
731
727
  "legal_risk": "high",
732
- }
728
+ },
733
729
  )
734
730
  gap_id_counter += 1
735
731
 
@@ -748,7 +744,7 @@ def identify_compliance_gaps(state: ComplianceAgentState) -> ComplianceAgentStat
748
744
  "estimated_time_to_fix": "15 minutes",
749
745
  "can_fix_retroactively": False,
750
746
  "legal_risk": "high",
751
- }
747
+ },
752
748
  )
753
749
  gap_id_counter += 1
754
750
 
@@ -768,7 +764,7 @@ def identify_compliance_gaps(state: ComplianceAgentState) -> ComplianceAgentStat
768
764
  # Message
769
765
  if len(gaps) == 0:
770
766
  state["messages"].append(
771
- AIMessage(content="🎉 No compliance gaps identified. Excellent work!")
767
+ AIMessage(content="🎉 No compliance gaps identified. Excellent work!"),
772
768
  )
773
769
  else:
774
770
  state["messages"].append(
@@ -777,8 +773,8 @@ def identify_compliance_gaps(state: ComplianceAgentState) -> ComplianceAgentStat
777
773
  f"{severity_dist['critical']} critical, "
778
774
  f"{severity_dist['high']} high, "
779
775
  f"{severity_dist['medium']} medium, "
780
- f"{severity_dist['low']} low"
781
- )
776
+ f"{severity_dist['low']} low",
777
+ ),
782
778
  )
783
779
 
784
780
  # Audit trail
@@ -793,7 +789,7 @@ def identify_compliance_gaps(state: ComplianceAgentState) -> ComplianceAgentStat
793
789
  "gaps": [{"id": g["gap_id"], "description": g["description"]} for g in gaps],
794
790
  },
795
791
  "user": "system",
796
- }
792
+ },
797
793
  )
798
794
 
799
795
  logger.info(f"Identified {len(gaps)} gaps: {severity_dist}")
@@ -802,8 +798,7 @@ def identify_compliance_gaps(state: ComplianceAgentState) -> ComplianceAgentStat
802
798
 
803
799
 
804
800
  def prepare_audit_documentation(state: ComplianceAgentState) -> ComplianceAgentState:
805
- """
806
- Step 4: Prepare comprehensive audit documentation package
801
+ """Step 4: Prepare comprehensive audit documentation package
807
802
 
808
803
  For positive outcomes:
809
804
  - Pre-prepared documentation reduces audit day stress
@@ -811,7 +806,6 @@ def prepare_audit_documentation(state: ComplianceAgentState) -> ComplianceAgentS
811
806
  - Gap remediation plan demonstrates proactive approach
812
807
  - Audit readiness score provides confidence metric
813
808
  """
814
-
815
809
  logger.info("[Step 4] Preparing audit documentation")
816
810
 
817
811
  # Generate documentation package
@@ -861,7 +855,13 @@ def prepare_audit_documentation(state: ComplianceAgentState) -> ComplianceAgentS
861
855
  }
862
856
 
863
857
  # Simulate storing documentation
864
- # TODO: Integrate with actual secure document storage (S3, SharePoint, etc.)
858
+ # TODO: Integration point - Secure document storage system
859
+ # RECOMMENDATION: Use cloud storage (AWS S3, Azure Blob, SharePoint) with:
860
+ # - Encryption at rest (AES-256) and in transit (TLS 1.2+)
861
+ # - HIPAA-compliant storage (BAA required)
862
+ # - Audit logging for all access
863
+ # - Retention policies per regulatory requirements
864
+ # For now, this example generates simulated URLs to demonstrate the workflow
865
865
  doc_url = f"https://secure-docs.hospital.com/compliance/{state['execution_id']}"
866
866
  doc_files = [
867
867
  "compliance_summary_report.pdf",
@@ -879,8 +879,8 @@ def prepare_audit_documentation(state: ComplianceAgentState) -> ComplianceAgentS
879
879
  # Message
880
880
  state["messages"].append(
881
881
  AIMessage(
882
- content=f"📄 Documentation package prepared: {len(doc_files)} files ready at {doc_url}"
883
- )
882
+ content=f"📄 Documentation package prepared: {len(doc_files)} files ready at {doc_url}",
883
+ ),
884
884
  )
885
885
 
886
886
  # Audit trail
@@ -895,7 +895,7 @@ def prepare_audit_documentation(state: ComplianceAgentState) -> ComplianceAgentS
895
895
  "readiness_score": doc_package["audit_readiness_score"],
896
896
  },
897
897
  "user": "system",
898
- }
898
+ },
899
899
  )
900
900
 
901
901
  logger.info(f"Documentation prepared: {doc_url}")
@@ -906,8 +906,7 @@ def prepare_audit_documentation(state: ComplianceAgentState) -> ComplianceAgentS
906
906
  def send_anticipatory_notifications(
907
907
  state: ComplianceAgentState,
908
908
  ) -> ComplianceAgentState:
909
- """
910
- Step 5: Send notifications to stakeholders with actionable information
909
+ """Step 5: Send notifications to stakeholders with actionable information
911
910
 
912
911
  For positive outcomes:
913
912
  - Early notification enables calm, planned response
@@ -915,7 +914,6 @@ def send_anticipatory_notifications(
915
914
  - Deadlines provide urgency without panic
916
915
  - Transparent reasoning builds trust in AI system
917
916
  """
918
-
919
917
  logger.info("[Step 5] Sending notifications to stakeholders")
920
918
 
921
919
  # Create action items from gaps
@@ -939,7 +937,7 @@ def send_anticipatory_notifications(
939
937
  "estimated_time": gap["estimated_time_to_fix"],
940
938
  "status": "pending",
941
939
  "created_at": datetime.now().isoformat(),
942
- }
940
+ },
943
941
  )
944
942
  action_id += 1
945
943
 
@@ -956,7 +954,11 @@ def send_anticipatory_notifications(
956
954
  notification = compose_notification(state, action_items)
957
955
 
958
956
  # Send notification
959
- # TODO: Integrate with actual notification system (email, SMS, Slack, etc.)
957
+ # TODO: Integration point - Multi-channel notification delivery
958
+ # IMPLEMENTATION AVAILABLE: See agents/notifications.py NotificationService class
959
+ # Use: notification_service.send_compliance_alert(severity, title, description, recipients)
960
+ # Supports Email (SMTP), Slack (webhooks), and SMS (Twilio) with graceful fallback
961
+ # For now, this example simulates notification to demonstrate stakeholder communication
960
962
  send_notification_to_recipients(notification, recipients, state["hospital_id"])
961
963
 
962
964
  state["notification_sent"] = True
@@ -967,8 +969,8 @@ def send_anticipatory_notifications(
967
969
  # Message
968
970
  state["messages"].append(
969
971
  AIMessage(
970
- content=f"📧 Notifications sent to {len(recipients)} recipients: {', '.join(recipients)}"
971
- )
972
+ content=f"📧 Notifications sent to {len(recipients)} recipients: {', '.join(recipients)}",
973
+ ),
972
974
  )
973
975
 
974
976
  # Audit trail
@@ -982,7 +984,7 @@ def send_anticipatory_notifications(
982
984
  "action_item_count": len(action_items),
983
985
  },
984
986
  "user": "system",
985
- }
987
+ },
986
988
  )
987
989
 
988
990
  logger.info(f"Notifications sent to: {recipients}")
@@ -991,8 +993,7 @@ def send_anticipatory_notifications(
991
993
 
992
994
 
993
995
  def schedule_continuous_monitoring(state: ComplianceAgentState) -> ComplianceAgentState:
994
- """
995
- Step 6: Schedule periodic re-checks until audit
996
+ """Step 6: Schedule periodic re-checks until audit
996
997
 
997
998
  For positive outcomes:
998
999
  - Regular monitoring tracks progress toward compliance
@@ -1000,7 +1001,6 @@ def schedule_continuous_monitoring(state: ComplianceAgentState) -> ComplianceAge
1000
1001
  - Trend analysis predicts audit readiness
1001
1002
  - Automated reminders keep team accountable
1002
1003
  """
1003
-
1004
1004
  logger.info("[Step 6] Scheduling continuous monitoring")
1005
1005
 
1006
1006
  days_until = state["days_until_audit"]
@@ -1031,8 +1031,8 @@ def schedule_continuous_monitoring(state: ComplianceAgentState) -> ComplianceAge
1031
1031
  state["messages"].append(
1032
1032
  AIMessage(
1033
1033
  content=f"⏰ Scheduled {frequency} monitoring until {state['next_audit_date']} "
1034
- f"(next check: {next_check_date[:10]})"
1035
- )
1034
+ f"(next check: {next_check_date[:10]})",
1035
+ ),
1036
1036
  )
1037
1037
 
1038
1038
  # Audit trail
@@ -1047,7 +1047,7 @@ def schedule_continuous_monitoring(state: ComplianceAgentState) -> ComplianceAge
1047
1047
  "until_date": state["next_audit_date"],
1048
1048
  },
1049
1049
  "user": "system",
1050
- }
1050
+ },
1051
1051
  )
1052
1052
 
1053
1053
  logger.info(f"Monitoring scheduled: {frequency} until {state['next_audit_date']}")
@@ -1061,12 +1061,10 @@ def schedule_continuous_monitoring(state: ComplianceAgentState) -> ComplianceAge
1061
1061
 
1062
1062
 
1063
1063
  def get_audit_requirements(audit_type: str) -> list[dict]:
1064
- """
1065
- Get compliance requirements for audit type
1064
+ """Get compliance requirements for audit type
1066
1065
 
1067
1066
  TODO: Load from database or configuration file
1068
1067
  """
1069
-
1070
1068
  # Example requirements for Joint Commission
1071
1069
  if audit_type == "joint_commission":
1072
1070
  return [
@@ -1118,15 +1116,13 @@ def get_audit_requirements(audit_type: str) -> list[dict]:
1118
1116
 
1119
1117
 
1120
1118
  def calculate_audit_readiness_score(state: ComplianceAgentState) -> float:
1121
- """
1122
- Calculate overall audit readiness score (0-100)
1119
+ """Calculate overall audit readiness score (0-100)
1123
1120
 
1124
1121
  Factors:
1125
1122
  - Compliance percentage (60% weight)
1126
1123
  - Gap severity (20% weight)
1127
1124
  - Time remaining (20% weight)
1128
1125
  """
1129
-
1130
1126
  # Factor 1: Compliance percentage
1131
1127
  compliance_score = state["compliance_percentage"]
1132
1128
 
@@ -1163,47 +1159,40 @@ def calculate_audit_readiness_score(state: ComplianceAgentState) -> float:
1163
1159
 
1164
1160
 
1165
1161
  def determine_assignee(gap: dict) -> str:
1166
- """
1167
- Determine who should be assigned to fix this gap
1162
+ """Determine who should be assigned to fix this gap
1168
1163
 
1169
1164
  Based on category and severity
1170
1165
  """
1171
-
1172
1166
  category = gap["category"]
1173
1167
  severity = gap["severity"]
1174
1168
 
1175
1169
  if category == "medication_safety":
1176
1170
  if severity == "critical":
1177
1171
  return "nurse_manager" # Manager handles critical safety issues
1178
- else:
1179
- return "charge_nurse"
1172
+ return "charge_nurse"
1180
1173
 
1181
- elif category == "documentation":
1174
+ if category == "documentation":
1182
1175
  return "charge_nurse" # Charge nurse coordinates documentation fixes
1183
1176
 
1184
- elif category == "patient_safety":
1177
+ if category == "patient_safety":
1185
1178
  if "restraint" in gap["item"].lower():
1186
1179
  return "provider" # Restraint orders require provider
1187
- else:
1188
- return "charge_nurse"
1180
+ return "charge_nurse"
1189
1181
 
1190
- elif category == "infection_control":
1182
+ if category == "infection_control":
1191
1183
  return "infection_control_nurse"
1192
1184
 
1193
- else:
1194
- return "charge_nurse" # Default
1185
+ return "charge_nurse" # Default
1195
1186
 
1196
1187
 
1197
1188
  def calculate_deadline(gap: dict, days_until_audit: int, audit_date: str) -> str:
1198
- """
1199
- Calculate appropriate deadline for fixing gap
1189
+ """Calculate appropriate deadline for fixing gap
1200
1190
 
1201
1191
  - Critical: 1 week or 25% of time remaining (whichever is sooner)
1202
1192
  - High: 2 weeks or 50% of time remaining
1203
1193
  - Medium: 1 month or 75% of time remaining
1204
1194
  - Low: 2 weeks before audit
1205
1195
  """
1206
-
1207
1196
  severity = gap["severity"]
1208
1197
 
1209
1198
  if severity == "critical":
@@ -1228,12 +1217,10 @@ def calculate_deadline(gap: dict, days_until_audit: int, audit_date: str) -> str
1228
1217
 
1229
1218
 
1230
1219
  def get_assignee_email(assignee: str, hospital_id: str) -> str:
1231
- """
1232
- Get email address for assignee
1220
+ """Get email address for assignee
1233
1221
 
1234
1222
  TODO: Look up from hospital staff database
1235
1223
  """
1236
-
1237
1224
  # Example mapping
1238
1225
  email_map = {
1239
1226
  "charge_nurse": f"charge.nurse@{hospital_id}.hospital.com",
@@ -1247,10 +1234,7 @@ def get_assignee_email(assignee: str, hospital_id: str) -> str:
1247
1234
 
1248
1235
 
1249
1236
  def compose_notification(state: ComplianceAgentState, action_items: list[dict]) -> dict:
1250
- """
1251
- Compose notification with all relevant information
1252
- """
1253
-
1237
+ """Compose notification with all relevant information"""
1254
1238
  days_until = state["days_until_audit"]
1255
1239
  compliance_pct = state["compliance_percentage"]
1256
1240
  gaps = state["compliance_gaps"]
@@ -1340,16 +1324,26 @@ without stress or rushed work during audit week.
1340
1324
 
1341
1325
 
1342
1326
  def send_notification_to_recipients(notification: dict, recipients: list[str], hospital_id: str):
1343
- """
1344
- Send notification via configured channels
1327
+ """Send notification via configured channels
1328
+
1329
+ TODO: Integration point - Multi-channel notification delivery
1330
+ IMPLEMENTATION AVAILABLE: See agents/notifications.py NotificationService class
1331
+
1332
+ Supported channels (already implemented):
1333
+ - Email (SMTP) - agents/notifications.py:send_email()
1334
+ - SMS (Twilio) - agents/notifications.py:send_sms()
1335
+ - Slack/Teams (webhooks) - agents/notifications.py:send_slack()
1336
+
1337
+ For compliance alerts, use:
1338
+ notification_service.send_compliance_alert(
1339
+ severity=notification["severity"],
1340
+ title=notification["title"],
1341
+ description=notification["summary"],
1342
+ recipients={"email": [...], "phone": [...]},
1343
+ )
1345
1344
 
1346
- TODO: Integrate with actual notification system
1347
- - Email (SMTP)
1348
- - SMS (Twilio)
1349
- - Slack/Teams (webhooks)
1350
- - In-app notifications
1345
+ This example simulates notifications to demonstrate the workflow.
1351
1346
  """
1352
-
1353
1347
  logger.info(f"Sending notification to: {recipients}")
1354
1348
 
1355
1349
  # Simulate sending
@@ -1369,10 +1363,10 @@ def send_notification_to_recipients(notification: dict, recipients: list[str], h
1369
1363
 
1370
1364
 
1371
1365
  async def run_compliance_agent(
1372
- hospital_id: str, audit_type: str = "joint_commission"
1366
+ hospital_id: str,
1367
+ audit_type: str = "joint_commission",
1373
1368
  ) -> ComplianceAgentState:
1374
- """
1375
- Run the compliance anticipation agent
1369
+ """Run the compliance anticipation agent
1376
1370
 
1377
1371
  Args:
1378
1372
  hospital_id: Hospital/facility identifier
@@ -1380,8 +1374,8 @@ async def run_compliance_agent(
1380
1374
 
1381
1375
  Returns:
1382
1376
  Final agent state with all results
1383
- """
1384
1377
 
1378
+ """
1385
1379
  logger.info(f"Starting Compliance Anticipation Agent for {hospital_id} ({audit_type})")
1386
1380
 
1387
1381
  # Create agent
@@ -1395,7 +1389,7 @@ async def run_compliance_agent(
1395
1389
 
1396
1390
  logger.info(
1397
1391
  f"Agent completed. Audit readiness score: "
1398
- f"{final_state.get('documentation_package', {}).get('audit_readiness_score', 0):.1f}"
1392
+ f"{final_state.get('documentation_package', {}).get('audit_readiness_score', 0):.1f}",
1399
1393
  )
1400
1394
 
1401
1395
  return final_state
@@ -1407,7 +1401,8 @@ if __name__ == "__main__":
1407
1401
  # Example usage
1408
1402
  async def main():
1409
1403
  result = await run_compliance_agent(
1410
- hospital_id="example_hospital_123", audit_type="joint_commission"
1404
+ hospital_id="example_hospital_123",
1405
+ audit_type="joint_commission",
1411
1406
  )
1412
1407
 
1413
1408
  print("\n" + "=" * 80)
@@ -1420,7 +1415,7 @@ if __name__ == "__main__":
1420
1415
  print(f"Action Items: {len(result['action_items'])}")
1421
1416
  print(f"Documentation: {result['documentation_url']}")
1422
1417
  print(
1423
- f"Audit Readiness: {result['documentation_package']['audit_readiness_score']:.1f}/100"
1418
+ f"Audit Readiness: {result['documentation_package']['audit_readiness_score']:.1f}/100",
1424
1419
  )
1425
1420
  print("=" * 80)
1426
1421