| name | openevidence-reference-architecture |
| description | Implement OpenEvidence reference architecture with best-practice project layout.
Use when designing new clinical AI integrations, reviewing project structure,
or establishing architecture standards for healthcare applications.
Trigger with phrases like "openevidence architecture", "openevidence best practices",
"openevidence project structure", "clinical ai architecture".
|
| allowed-tools | Read, Grep |
| version | 1.0.0 |
| license | MIT |
| author | Jeremy Longshore <jeremy@intentsolutions.io> |
OpenEvidence Reference Architecture
Overview
Production-ready architecture patterns for OpenEvidence clinical AI integrations in healthcare environments.
Prerequisites
- Understanding of layered architecture
- OpenEvidence SDK knowledge
- Healthcare compliance requirements
- TypeScript/Node.js project setup
Project Structure
clinical-evidence-api/
├── src/
│ ├── openevidence/
│ │ ├── client.ts # Singleton client wrapper
│ │ ├── config.ts # Environment configuration
│ │ ├── types.ts # TypeScript types
│ │ ├── errors.ts # Custom error classes
│ │ ├── cache.ts # Caching layer
│ │ └── handlers/
│ │ ├── webhooks.ts # Webhook handlers
│ │ └── events.ts # Event processing
│ ├── services/
│ │ └── clinical/
│ │ ├── index.ts # Service facade
│ │ ├── query.ts # Clinical query service
│ │ ├── deepconsult.ts # DeepConsult service
│ │ └── drug-info.ts # Drug information service
│ ├── api/
│ │ ├── routes/
│ │ │ ├── clinical.ts # Clinical query endpoints
│ │ │ └── webhooks.ts # Webhook endpoints
│ │ └── middleware/
│ │ ├── auth.ts # Authentication
│ │ ├── audit.ts # HIPAA audit logging
│ │ └── rate-limit.ts # Rate limiting
│ ├── integrations/
│ │ ├── ehr/
│ │ │ ├── fhir.ts # FHIR integration
│ │ │ ├── epic.ts # Epic EHR hooks
│ │ │ └── cerner.ts # Cerner integration
│ │ └── notifications/
│ │ ├── email.ts # Email notifications
│ │ └── push.ts # Push notifications
│ ├── compliance/
│ │ ├── hipaa/
│ │ │ ├── audit-log.ts # HIPAA audit logging
│ │ │ ├── phi-handler.ts # PHI sanitization
│ │ │ └── encryption.ts # Data encryption
│ │ └── retention.ts # Data retention policies
│ └── jobs/
│ ├── cleanup.ts # Data cleanup job
│ └── reporting.ts # Usage reporting job
├── tests/
│ ├── unit/
│ │ └── services/
│ ├── integration/
│ │ └── openevidence/
│ └── clinical-validation/
│ └── known-answers/
├── config/
│ ├── default.json
│ ├── development.json
│ ├── staging.json
│ └── production.json
├── docs/
│ ├── architecture.md
│ ├── runbook.md
│ └── api-reference.md
└── scripts/
├── migrate.sh
└── deploy.sh
Layer Architecture
┌─────────────────────────────────────────────────────┐
│ API Layer │
│ (Controllers, Routes, Webhooks, Middleware) │
├─────────────────────────────────────────────────────┤
│ Service Layer │
│ (Business Logic, Orchestration, Validation) │
├─────────────────────────────────────────────────────┤
│ OpenEvidence Layer │
│ (Client, Types, Caching, Error Handling) │
├─────────────────────────────────────────────────────┤
│ Compliance Layer │
│ (HIPAA Audit, PHI Handling, Encryption) │
├─────────────────────────────────────────────────────┤
│ Integration Layer │
│ (EHR/FHIR, Notifications, External Services) │
├─────────────────────────────────────────────────────┤
│ Infrastructure Layer │
│ (Database, Cache, Queue, Monitoring) │
└─────────────────────────────────────────────────────┘
Key Components
Step 1: Client Wrapper with Caching & Monitoring
import { OpenEvidenceClient } from '@openevidence/sdk';
import { ClinicalQueryCache } from './cache';
import { MetricsCollector } from '../monitoring/metrics';
import { HIPAAAuditLogger } from '../compliance/hipaa/audit-log';
export interface OpenEvidenceServiceConfig {
apiKey: string;
orgId: string;
baseUrl: string;
timeout: number;
cache: ClinicalQueryCache;
metrics: MetricsCollector;
auditLogger: HIPAAAuditLogger;
}
export class OpenEvidenceService {
private client: OpenEvidenceClient;
private cache: ClinicalQueryCache;
private metrics: MetricsCollector;
private auditLogger: HIPAAAuditLogger;
constructor(: ) {
. = ({
: config.,
: config.,
: config.,
: config.,
});
. = config.;
. = config.;
. = config.;
}
(
: ,
:
): <> {
timer = ..();
{
cached = ..(request., request.);
(cached) {
..();
timer.({ : });
cached;
}
..();
response = ..(request);
..(request., request., response);
..(context., context., response., );
timer.({ : });
response;
} (: ) {
..(, { : error. });
..(context., context., , );
timer.({ : });
error;
}
}
(
: ,
:
): <> {
consultId = ...(request);
..(context., context., consultId, );
consultId;
}
(): <> {
{
start = .();
...();
{
: ,
: .() - start,
};
} (: ) {
{ : , : error. };
}
}
}
Step 2: Service Facade
import { OpenEvidenceService } from '../../openevidence/client';
import { PHIHandler } from '../../compliance/hipaa/phi-handler';
export class ClinicalEvidenceService {
constructor(
private openEvidence: OpenEvidenceService,
private phiHandler: PHIHandler
) {}
async queryClinicalEvidence(
question: string,
patientContext: PatientContext | undefined,
context: RequestContext
): Promise<FormattedClinicalAnswer> {
const sanitizedRequest = this.phiHandler.sanitizeQuery(question, patientContext);
const response = await this.openEvidence.query(sanitizedRequest, context);
return this.formatClinicalAnswer(response);
}
async (
: ,
: ,
:
): <{ : ; : }> {
sanitizedQuestion = ..(question);
consultId = ..({
: sanitizedQuestion,
: {
: options.,
: options.,
: options.,
},
}, context);
{
consultId,
: ,
};
}
(
: [],
:
): <> {
question = ;
response = ..({
question,
: {
: ,
: ,
},
}, context);
.(response);
}
(: ): {
{
: response..()[] + ,
: response.,
: response..( ({
: c.,
: c.,
: c.,
})),
: {
: response.,
: response. > ? : response. > ? : ,
},
: ,
};
}
(: ): {
answerLower = response..();
{
: !answerLower.(),
: .(answerLower),
: response.,
: response.,
};
}
(: ): | | | {
(text.() || text.()) ;
(text.() || text.()) ;
(text.()) ;
;
}
}
Step 3: EHR Integration Layer
import { ClinicalEvidenceService } from '../../services/clinical';
interface CDSHooksRequest {
hook: string;
hookInstance: string;
context: {
patientId: string;
encounterId?: string;
medications?: FHIRMedication[];
conditions?: FHIRCondition[];
};
prefetch?: {
patient?: FHIRPatient;
medications?: FHIRBundle<FHIRMedication>;
};
}
interface CDSHooksResponse {
cards: CDSCard[];
}
export class FHIRIntegration {
constructor(private clinicalService: ClinicalEvidenceService) {}
async handleCDSHook(request: CDSHooksRequest): Promise<CDSHooksResponse> {
switch (request.hook) {
case 'medication-prescribe':
return .(request);
:
.(request);
:
{ : [] };
}
}
(
:
): <> {
medications = request..?.(
m.?.
).() [];
(medications. < ) {
{ : [] };
}
interaction = ..(
medications,
{ : , : }
);
(!interaction.) {
{ : [] };
}
{
: [{
: crypto.(),
: ,
: interaction.,
: interaction. === ? : ,
: {
: ,
: ,
},
: interaction. === ? [{
: ,
: crypto.(),
}] : ,
}],
};
}
(: ): <> {
{ : [] };
}
}
Data Flow Diagram
User/EHR Request
│
▼
┌─────────────────┐
│ API Gateway │
│ (Auth, Rate) │
└────────┬────────┘
│
▼
┌─────────────────┐ ┌─────────────────┐
│ PHI Sanitizer │───▶│ HIPAA Audit │
└────────┬────────┘ └─────────────────┘
│
▼
┌─────────────────┐ ┌─────────────────┐
│ Clinical │───▶│ Cache Layer │
│ Query Service │ │ (Redis) │
└────────┬────────┘ └────────┬────────┘
│ │
▼ (cache miss) │
┌─────────────────┐ │
│ OpenEvidence │◄────────────┘
│ API Client │ (cache hit)
└────────┬────────┘
│
▼
┌─────────────────┐
│ OpenEvidence │
│ Cloud API │
└─────────────────┘
Configuration Management
import convict from 'convict';
const config = convict({
env: {
doc: 'Application environment',
format: ['development', 'staging', 'production'],
default: 'development',
env: 'NODE_ENV',
},
openevidence: {
apiKey: {
doc: 'OpenEvidence API key',
format: String,
default: '',
env: 'OPENEVIDENCE_API_KEY',
sensitive: true,
},
orgId: {
doc: 'OpenEvidence organization ID',
format: String,
default: '',
env: 'OPENEVIDENCE_ORG_ID',
},
baseUrl: {
doc: 'OpenEvidence API base URL',
format: 'url',
default: 'https://api.openevidence.com',
env: 'OPENEVIDENCE_BASE_URL',
},
timeout: {
doc: 'Request timeout in milliseconds',
format: ,
: ,
: ,
},
},
: {
: {
: ,
: ,
: ,
},
: {
: ,
: ,
: ,
},
},
: {
: {
: ,
: ,
: ,
},
},
});
config.();
config.({ : });
config;
Output
- Layered architecture with separation of concerns
- HIPAA-compliant data handling
- EHR integration ready
- Comprehensive caching
- Health checks and monitoring
Architecture Checklist
Resources
Flagship Skills
For multi-environment setup, see openevidence-multi-env-setup.