404 Not Found |
Unknown specialty code |
Use standard specialt
Execute OpenEvidence secondary workflow: DeepConsult Research Synthesis.
ReadWriteEditBash(npm:*)Grep
OpenEvidence — Evidence Review & Citations
Overview
Search medical evidence, manage citations, and generate formatted evidence reports
through OpenEvidence. Use this workflow to find clinical studies for a specific
question, build citation collections for literature reviews, or produce structured
evidence summaries with graded recommendations. This is the secondary workflow —
for DeepConsult research synthesis, see openevidence-core-workflow-a.
Instructions
Step 1: Search the Evidence Database
const results = await client.evidence.search({
query: 'SGLT2 inhibitors cardiovascular outcomes type 2 diabetes',
filters: {
study_type: ['rct', 'meta_analysis', 'systematic_review'],
year_range: { min: 2020, max: 2026 },
evidence_level: ['1a', '1b', '2a'],
},
limit: 25,
sort: 'relevance',
});
console.log(`Found ${results.total} studies`);
results.items.forEach(s =>
console.log(` [${s.evidence_level}] ${s.title} (${s.journal}, ${s.year}) — ${s.citations} citations`)
);
Step 2: Build a Citation Collection
const collection = await client.citations.create({
name: 'SGLT2i CV Outcomes Review — April 2026',
study_ids: results.items.slice(0, 15).map(s => s.id),
tags: ['cardiology', 'diabetes', 'sglt2i'],
});
console.log(`Collection ${collection.id}: ${collection.study_count} studies`);
await client.citations.addByDoi(collection.id, { doi: '10.1056/NEJMoa2034577' });
Step 3: Grade Evidence and Extract Key Findings
const graded = await client.evidence.grade(collection.id, {
framework: 'GRADE', // GRADE | Oxford | USPSTF
outcome: 'major_adverse_cardiovascular_events',
});
graded.findings.forEach(f =>
console.log(`${f.outcome}: ${f.grade} (${f.certainty}) — ${f.summary}`)
);
console.log(`Overall recommendation: ${graded.recommendation}`);
Step 4: Generate a Formatted Evidence Report
const report = await client.reports.generate({
collection_id: collection.id,
format: 'structured',
sections: ['clinical_question', 'search_strategy', 'evidence_table', 'grade_summary', 'references'],
citation_style: 'AMA',
});
console.log(`Report generated: ${report.page_count} pages`);
console.log(`Download: ${report.download_url}`);
HIPAA Notice
- HIPAA-compliant and SOC 2 Type II certified — never include patient identifiers
- Use de-identified clinical scenarios only; ensure BAA is in place before handling PHI
Error Handling
| Issue |
Cause |
Fix |
Cost Tuning for OpenEvidence.
ReadWriteEditGrep
OpenEvidence Cost Tuning
Optimization Strategies
- Cache frequent API calls
- Batch requests where possible
- Use appropriate API tier
- Monitor usage dashboards
Usage Tracking
let totalCalls = 0;
async function tracked(fn: () => Promise<any>) {
totalCalls++;
console.log(`OpenEvidence API calls today: ${totalCalls}`);
return fn();
}
Resources
Next Steps
See openevidence-reference-architecture.
Data Handling for OpenEvidence.
ReadWriteEditGrep
OpenEvidence Data Handling
Overview
OpenEvidence provides AI-powered clinical evidence synthesis for healthcare professionals. Data types include clinical queries (potentially containing PHI), evidence citations from medical literature, patient-contextualized responses, research paper references, and usage analytics. All data handling must comply with HIPAA (PHI safeguards, minimum necessary standard, BAA requirements), GDPR for EU clinicians, and FDA guidance on clinical decision support. Query data may contain patient identifiers, diagnoses, or treatment details that require de-identification before storage or analytics.
Data Classification
| Data Type |
Sensitivity |
Retention |
Encryption |
| Clinical queries (may contain PHI) |
Critical |
De-identify within 24h, purge raw in 7 days |
AES-256 + TLS, field-level for PHI |
| Evidence citations |
Low |
Indefinite (public literature) |
TLS in transit |
| Patient-contextualized responses |
High (derived PHI) |
30 days max, then de-identify |
AES-256 at rest |
| Research paper metadata |
Low |
Indefinite |
TLS in transit |
| Clinician usage analytics |
Medium |
1 year (de-identified) |
AES-256 at rest |
Data Import
interface ClinicalQuery {
queryId: string; clinicianId: string; queryText: string;
patientContext?: { age?: number; sex?: string; conditions?: string[] };
timestamp: string;
}
async function submitClinicalQuery(query: ClinicalQuery): Promise<string> {
const sanitized = { ...query, queryText: deidentifyPHI(query.queryText) };
const res = await fetch('https://api.openevidence.com/v1/query', {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.OPENEVIDENCE_API_KEY}`, 'Content-Type': 'application/json' },
body: JSON.stringify(sanitized),
});
return (await res.json()).evidenceId;
}
function deidentifyPHI(text: string): string {
return text
.replace(/\b(MRN|mrn)[:\s]?\d{6,}\b/g, '[MRN_REDACTED]')
.replace(/\b\d{3}-\d{2}-\d{4}\b/g, '[SSN_REDACTED]')
.replace(/\b(DOB|dob)[:\s]?\d{1,2}\/\d{1,2}\/\d{2,4}\b/g, '[DOB_REDACTED]')
.replace(/\b[A-Z][a-z]+ [A-Z][a-z]+, (MD|DO|NP|PA)\b/g, '[PROVIDER_REDACTED]');
}
Data Export
async function exportEvidenceSummary(queryIds: string[]) {
const summaries = [];
for (const id of queryIds) {
const res = await fetch(`https://api.openevidence.com/v1/evidence/${id}`, {
headers: { Authorization: `Bearer ${process.env.OPENEVIDENCE_API_KEY}` },
});
const data = await res.json();
summaries.push({ queryId: id, citations:
Debug Bundle for OpenEvidence.
ReadBash(curl:*)Grep
OpenEvidence Debug Bundle
Overview
This debug bundle collects diagnostic evidence from OpenEvidence clinical decision support
API integrations for troubleshooting evidence retrieval, clinical query accuracy, and
response latency issues. It captures API token validation, clinical query endpoint health,
evidence citation availability, model version metadata, and response time benchmarks. The
resulting tarball provides the evidence needed to diagnose query failures, missing clinical
references, citation linking errors, and compliance logging gaps without requiring direct
OpenEvidence dashboard access.
Prerequisites
curl, jq, tar installed
OPENEVIDENCEAPIKEY set (API key from OpenEvidence developer portal)
- Network access to
api.openevidence.com (HTTPS 443)
Debug Collection Script
#!/bin/bash
set -euo pipefail
BUNDLE="debug-openevidence-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$BUNDLE"
# Environment check
echo "=== Environment ===" > "$BUNDLE/environment.txt"
echo "API Key: ${OPENEVIDENCE_API_KEY:+SET (redacted)}" >> "$BUNDLE/environment.txt"
echo "Node: $(node -v 2>/dev/null || echo 'not installed')" >> "$BUNDLE/environment.txt"
echo "Python: $(python3 --version 2>/dev/null || echo 'not installed')" >> "$BUNDLE/environment.txt"
echo "Timestamp: $(date -u)" >> "$BUNDLE/environment.txt"
# API connectivity — health check
echo "=== API Health ===" > "$BUNDLE/api-health.txt"
curl -sf -o "$BUNDLE/api-health.txt" -w "HTTP %{http_code} in %{time_total}s\n" \
-H "Authorization: Bearer ${OPENEVIDENCE_API_KEY}" \
"https://api.openevidence.com/v1/health" 2>&1 || echo "UNREACHABLE" > "$BUNDLE/api-health.txt"
# Clinical query test (benign test query)
echo "=== Query Test ===" > "$BUNDLE/query-test.json"
curl -sf -X POST "https://api.openevidence.com/v1/query" \
-H "Authorization: Bearer ${OPENEVIDENCE_API_KEY}" \
-H "Content-Type: application/json" \
-d '{"query":"What is the recommended first-line treatment for hypertension?","max_results":3}' \
>> "$BUNDLE/query-test.json" 2>&1 || echo '{"error":"QUERY_FAILED"}' > "$BUNDLE/query-test.json"
# Evidence citation retrieval
echo "=== Citations ===" > "$BUNDLE/citations.json"
QUERY_ID=$(jq -r '.queryId // empty' "$BUNDLE/query-test.json" 2>/dev/null)
if [ -n "${QUERY_ID:-}" ]; then
curl -sf -H "Authorization: Bearer ${
Deploy Integration for OpenEvidence.
ReadWriteEditGrep
OpenEvidence Deploy Integration
Overview
Deploy a containerized OpenEvidence clinical evidence integration service with Docker. This skill covers building a HIPAA-conscious production image that connects to the OpenEvidence API for querying clinical evidence, retrieving medical literature summaries, and validating treatment recommendations. Includes environment configuration with audit logging and data-at-rest encryption flags, health checks that verify API connectivity without exposing PHI, and rolling update strategies that maintain service availability during critical clinical query periods.
Docker Configuration
FROM node:20-slim AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY tsconfig.json ./
COPY src/ ./src/
RUN npm run build
FROM node:20-slim
RUN addgroup --system app && adduser --system --ingroup app app
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package*.json ./
RUN mkdir -p /app/audit-logs && chown app:app /app/audit-logs
USER app
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
CMD ["node", "dist/index.js"]
Environment Variables
export OPENEVIDENCE_API_KEY="oe_live_xxxxxxxxxxxx"
export OPENEVIDENCE_BASE_URL="https://api.openevidence.com/v1"
export OPENEVIDENCE_ORG_ID="org_xxxxxxxxxxxx"
export HIPAA_AUDIT_LOG="true"
export HIPAA_ENCRYPT_AT_REST="true"
export LOG_LEVEL="info"
export PORT="3000"
export NODE_ENV="production"
Health Check Endpoint
import express from 'express';
const app = express();
app.get('/health', async (req, res) => {
try {
const response = await fetch(`${process.env.OPENEVIDENCE_BASE_URL}/status`, {
headers: { 'Authorization': `Bearer ${process.env.OPENEVIDENCE_API_KEY}` },
});
if (!response.ok) throw new Error(`OpenEvidence API returned ${response.status}`);
// Health response must not contain PHI or query content
res.json({ status: 'healthy', service: 'openevidence-integration', audit: process.env.HIPAA_AUDIT_LOG === 'true', timestamp: new Date().toISOString() });
} catch (error) {
res.status(503).json({ status: 'unhealthy', error: (error as Error).message });
}
});
Deployment Steps
Step 1: Build
docker build -t openevidence-integration:latest .
Step 2: Run
docker run -d --name openevidence-integration \
-p 3000:3000 \
-v /var/log/openevidence:/app/audit-logs \
-e OPENEVIDENCE_API_KEY -e OPENEVIDENCE_BASE_URL -e OPENEVIDENCE_ORG_ID \
-e HIPAA_AUDIT_LOG=true -e HIPAA
Enterprise Rbac for OpenEvidence.
ReadWriteEditGrep
OpenEvidence Enterprise RBAC
Overview
OpenEvidence delivers AI-powered clinical decision support using peer-reviewed medical literature. Enterprise RBAC controls access to clinical queries, PHI-adjacent data, and research datasets. Clinicians query evidence with full access. Researchers access de-identified datasets and can create study cohorts. Admins manage institutional access, SSO configuration, and compliance settings. HIPAA requires strict audit logging of every clinical query, PHI access event, and data export. Institutional access agreements define which evidence libraries each organization can query.
Role Hierarchy
| Role |
Permissions |
Scope |
| Institutional Admin |
Manage users, SSO config, compliance settings, usage analytics |
Organization-wide |
| Clinician |
Query clinical evidence, view full citations, bookmark findings |
Institutional library |
| Researcher |
Access de-identified datasets, create study cohorts, export data |
Approved studies |
| Medical Student |
Query evidence with supervised access, no PHI datasets |
Educational library |
| Auditor |
Read-only access to query logs and compliance reports |
Organization-wide |
Permission Check
async function checkClinicalAccess(userId: string, resource: string, accessLevel: string): Promise<boolean> {
const response = await fetch(`${OE_API}/v1/institutions/${INSTITUTION_ID}/permissions`, {
headers: { Authorization: `Bearer ${OE_API_TOKEN}`, 'Content-Type': 'application/json' },
});
const perms = await response.json();
const user = perms.members.find((m: any) => m.id === userId);
if (!user) return false;
const allowed = ROLE_ACCESS[user.role];
return allowed?.resources.includes(resource) && allowed.levels.includes(accessLevel);
}
Role Assignment
async function assignInstitutionalRole(email: string, role: string, library: string): Promise<void> {
await fetch(`${OE_API}/v1/institutions/${INSTITUTION_ID}/members`, {
method: 'POST',
headers: { Authorization: `Bearer ${OE_API_TOKEN}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ email, role, libraryAccess: library, hipaaAcknowledged: true }),
});
}
async function revokeAccess(email: string): Promise<void> {
await fetch(`${OE_API}/v1/institutions/${INSTITUTION_ID}/members/${email}`, {
method: 'DELETE',
headers: { Authorization: `Bearer ${OE_API_TOKEN}` },
});
}
Audit Logging
interface OpenEvidenceAuditEntry {
timestamp: string; userId: string; role: string;
action: 'clinical_qu
Create a minimal working OpenEvidence example.
ReadWriteEditBash(npm:*)Grep
OpenEvidence Hello World
Overview
Minimal working examples demonstrating core OpenEvidence API functionality.
Instructions
Step 1: Clinical Query
const result = await client.query({
question: 'What is the recommended treatment for acute migraine in adults?',
context: 'emergency_department',
evidence_level: 'high', // Filter by evidence quality
max_citations: 10
});
console.log('Answer:', result.answer);
console.log('Confidence:', result.confidence);
result.citations.forEach(c =>
console.log(` [${c.journal}] ${c.title} (${c.year}) — ${c.evidence_level}`)
);
Step 2: Drug Interaction Check
const interactions = await client.interactions.check({
medications: ['metformin', 'lisinopril', 'atorvastatin'],
patient_context: { age: 65, conditions: ['diabetes', 'hypertension'] }
});
interactions.forEach(i =>
console.log(`${i.drug1} + ${i.drug2}: ${i.severity} — ${i.description}`)
);
Step 3: Guideline Lookup
const guidelines = await client.guidelines.search({
condition: 'hypertension',
source: ['ACC/AHA', 'ESC'],
year_min: 2023
});
guidelines.forEach(g =>
console.log(`${g.source}: ${g.title} (${g.year})`)
);
Error Handling
| Error |
Cause |
Solution |
| Auth error |
Invalid credentials |
Check OPENEVIDENCEAPIKEY |
| Not found |
Invalid endpoint |
Verify API URL |
| Rate limit |
Too many requests |
Implement backoff |
Resources
Next Steps
See openevidence-local-dev-loop.
Incident Runbook for OpenEvidence.
ReadWriteEditGrep
OpenEvidence Incident Runbook
Severity
| Level |
Condition |
Response |
| P1 |
API down |
Immediate |
| P2 |
Degraded |
15 min |
| P3 |
Intermittent |
1 hour |
Triage
- Check OpenEvidence status page
- Verify API key is valid
- Test connectivity with curl
- Check error logs for patterns
Mitigation
- Enable cached/fallback responses
- Queue requests for retry
- Notify affected teams
Resources
Next Steps
See openevidence-data-handling.
Install and configure OpenEvidence SDK/API authentication.
ReadWriteEditBash(npm:*)Bash(pip:*)Grep
OpenEvidence Install & Auth
Overview
Set up OpenEvidence Medical AI API for clinical decision support and evidence-based queries.
Prerequisites
- OpenEvidence account and API access
- API key/credentials from OpenEvidence dashboard
- Node.js 18+ or Python 3.8+
Instructions
Step 1: Install SDK
npm install @openevidence/sdk
# API key from OpenEvidence developer portal
Step 2: Configure Authentication
export OPENEVIDENCE_API_KEY="your-api-key-here"
echo 'OPENEVIDENCE_API_KEY=your-api-key' >> .env
Step 3: Verify Connection (TypeScript)
import { OpenEvidenceClient } from '@openevidence/sdk';
const client = new OpenEvidenceClient({
apiKey: process.env.OPENEVIDENCE_API_KEY,
organization: process.env.OPENEVIDENCE_ORG_ID
});
const result = await client.query({ question: 'What are first-line treatments for Type 2 diabetes?' });
console.log(`Answer: ${result.answer.substring(0, 100)}...`);
console.log(`Citations: ${result.citations.length} references`);
Step 4: Verify Connection (Python)
import openevidence
client = openevidence.Client(api_key=os.environ['OPENEVIDENCE_API_KEY'])
result = client.query(question='What are first-line treatments for Type 2 diabetes?')
print(f'Answer: {result.answer[:100]}...')
print(f'Citations: {len(result.citations)} references')
Error Handling
| Error |
Code |
Solution |
| Invalid API key |
401 |
Verify credentials in dashboard |
| Permission denied |
403 |
Check API scopes/permissions |
| Rate limited |
429 |
Implement backoff |
Resources
Next Steps
After auth, proceed to openevidence-hello-world.
Local Dev Loop for OpenEvidence.
ReadWriteEdit
OpenEvidence Local Dev Loop
Overview
Local development workflow for OpenEvidence clinical decision support API integration. Provides a fast feedback loop with mock evidence queries, citation responses, and clinical summary data so you can build health-tech tools without consuming live API quota. Toggle between mock mode for rapid iteration and sandbox mode for validating against the real OpenEvidence platform. Always use de-identified data in development.
Environment Setup
cp .env.example .env
# Set your credentials:
# OPENEVIDENCE_API_KEY=oe_xxxxxxxxxxxx
# OPENEVIDENCE_BASE_URL=https://api.openevidence.com/v1
# MOCK_MODE=true
npm install express axios dotenv tsx typescript @types/node
npm install -D vitest supertest @types/express
Dev Server
// src/dev/server.ts
import express from "express";
import { createProxyMiddleware } from "http-proxy-middleware";
const app = express();
app.use(express.json());
const MOCK = process.env.MOCK_MODE === "true";
if (!MOCK) {
app.use("/v1", createProxyMiddleware({
target: process.env.OPENEVIDENCE_BASE_URL,
changeOrigin: true,
headers: { Authorization: `Bearer ${process.env.OPENEVIDENCE_API_KEY}` },
}));
} else {
const { mountMockRoutes } = require("./mocks");
mountMockRoutes(app);
}
app.listen(3008, () => console.log(`OpenEvidence dev server on :3008 [mock=${MOCK}]`));
Mock Mode
// src/dev/mocks.ts — realistic clinical decision support responses (de-identified)
export function mountMockRoutes(app: any) {
app.post("/v1/query", (req: any, res: any) => res.json({
query: req.body.question,
answer: "Based on current evidence, first-line treatment for type 2 diabetes includes metformin combined with lifestyle modifications. HbA1c targets should be individualized.",
citations: [
{ title: "ADA Standards of Care 2025", source: "Diabetes Care", doi: "10.2337/dc25-S009", year: 2025 },
{ title: "Metformin Meta-Analysis", source: "NEJM", doi: "10.1056/NEJMoa2412345", year: 2024 },
],
confidenceScore: 0.92,
}));
app.get("/v1/topics", (_req: any, res: any) => res.json([
{ id: "top_1", name: "Diabetes Management", questionCount: 245 },
{ id: "top_2", name: "Hypertension", questionCount: 189 },
{ id: "top_3", name: "Oncology Screening", questionCount: 134 },
]));
app.get("/v1/citations/:doi", (req: any, res: any) => res.json({
doi: req.params.doi, title: "ADA Standards of Care 2025", abstract: "Annual update to diabetes management guidelines...",
journal: "Diabetes Care", year: 2025, evidenceLevel: "Level I",
}))
Migration Deep Dive for OpenEvidence.
ReadWriteEditGrep
OpenEvidence Migration Deep Dive
Migration Strategies
- Parallel run: Run old and new systems simultaneously
- Strangler fig: Gradually route traffic to OpenEvidence
- Big bang: Switch all at once (risky)
Migration Checklist
- [ ] API mapping documented
- [ ] Data migration plan
- [ ] Rollback procedure
- [ ] Performance baseline
- [ ] Team training complete
Resources
Next Steps
Start with openevidence-install-auth.
Multi Env Setup for OpenEvidence.
ReadWriteEditGrep
OpenEvidence Multi-Environment Setup
Overview
OpenEvidence clinical AI requires strict environment separation to maintain HIPAA compliance across the data lifecycle. Development uses only synthetic patient data with no PHI access, staging operates on de-identified datasets for clinical validation, and production handles full PHI under BAA-covered infrastructure. Each environment enforces its own audit logging, encryption, and access control policies. Misconfigured environments risk PHI exposure and regulatory violations, making environment validation a hard requirement at startup.
Environment Configuration
const openEvidenceConfig = (env: string) => ({
development: {
apiKey: process.env.OPENEVIDENCE_API_KEY_DEV!, baseUrl: "https://api.dev.openevidence.com/v1",
dataClassification: "synthetic", phiEnabled: false, auditLevel: "basic", encryptionRequired: false,
},
staging: {
apiKey: process.env.OPENEVIDENCE_API_KEY_STG!, baseUrl: "https://api.staging.openevidence.com/v1",
dataClassification: "de-identified", phiEnabled: false, auditLevel: "full", encryptionRequired: true,
},
production: {
apiKey: process.env.OPENEVIDENCE_API_KEY_PROD!, baseUrl: "https://api.openevidence.com/v1",
dataClassification: "phi", phiEnabled: true, auditLevel: "full", encryptionRequired: true,
},
}[env]);
Environment Files
# Per-env files: .env.development, .env.staging, .env.production
OPENEVIDENCE_API_KEY_{DEV|STG|PROD}=<api-key>
OPENEVIDENCE_BASE_URL=https://api.{dev.|staging.|""}openevidence.com/v1
OPENEVIDENCE_DATA_CLASS={synthetic|de-identified|phi}
OPENEVIDENCE_PHI_ENABLED={false|false|true}
OPENEVIDENCE_AUDIT_LEVEL={basic|full|full}
OPENEVIDENCE_BAA_ID=<baa-id> # production only
Environment Validation
function validateOpenEvidenceEnv(env: string): void {
const suffix = { development: "_DEV", staging: "_STG", production: "_PROD" }[env];
const required = [`OPENEVIDENCE_API_KEY${suffix}`, "OPENEVIDENCE_BASE_URL", "OPENEVIDENCE_DATA_CLASS"];
if (env === "production") required.push("OPENEVIDENCE_BAA_ID");
if (env !== "development") required.push("OPENEVIDENCE_AUDIT_LEVEL");
const missing = required.filter((k) => !process.env[k]);
if (missing.length) throw new Error(`Missing OpenEvidence vars for ${env}: ${missing.join(", ")}`);
if (env === "production" && process.env.OPENEVIDENCE_PHI_ENABLED !== "true")
throw new Error("HIPAA violation: PHI must be enabled in production");
}
Promotion Workflow
# 1. Run clinical queries against synth
Observability for OpenEvidence.
ReadWriteEditGrep
OpenEvidence Observability
Overview
OpenEvidence delivers clinical evidence queries where response accuracy and freshness have direct patient safety implications. Monitor query response times to ensure clinicians get timely answers, track evidence freshness to catch stale citations, and audit every query for compliance. Observability must also verify citation accuracy and maintain complete audit logs for regulatory requirements (HIPAA, clinical decision support standards).
Key Metrics
| Metric |
Type |
Target |
Alert Threshold |
| Query response time p95 |
Histogram |
< 3s |
> 8s |
| Evidence freshness |
Gauge |
< 7 days median |
> 30 days |
| Citation accuracy rate |
Gauge |
> 95% |
< 90% |
| API error rate |
Gauge |
< 0.5% |
> 2% |
| Audit log completeness |
Gauge |
100% |
< 99.9% |
| Daily query volume |
Counter |
Within quota |
> 90% quota |
Instrumentation
async function trackClinicalQuery(queryType: string, fn: () => Promise<any>) {
const start = Date.now();
const traceId = crypto.randomUUID();
try {
const result = await fn();
metrics.histogram('openevidence.query.latency', Date.now() - start, { queryType });
metrics.increment('openevidence.query.total', { queryType });
auditLog.record({ traceId, queryType, status: 'ok', latency: Date.now() - start });
return result;
} catch (err) {
metrics.increment('openevidence.query.errors', { queryType, error: err.code });
auditLog.record({ traceId, queryType, status: 'error', error: err.message });
throw err;
}
}
Health Check Dashboard
async function openEvidenceHealth(): Promise<Record<string, string>> {
const latencyP95 = await metrics.query('openevidence.query.latency', 'p95', '5m');
const errorRate = await metrics.query('openevidence.query.error_rate', 'avg', '5m');
const freshness = await openEvAdmin.getMedianEvidenceAge();
return {
query_latency: latencyP95 < 3000 ? 'healthy' : 'slow',
error_rate: errorRate < 0.005 ? 'healthy' : 'degraded',
evidence_freshness: freshness < 7 ? 'healthy' : 'stale',
};
}
Alerting Rules
const alerts = [
{ metric: 'openevidence.query.latency_p95', condition: '> 8s', window: '10m', severity: 'warning' },
{ metric: 'openevidence.query.error_rate', condition: '> 0.02', window: '5m', severit
Performance Tuning for OpenEvidence.
ReadWriteEditGrep
OpenEvidence Performance Tuning
Overview
OpenEvidence's clinical API handles evidence query response times, citation batch retrieval, and complex multi-condition query optimization. Clinical evidence queries can take 2-5 seconds as the system searches across thousands of medical studies and synthesizes responses. Citation batch retrieval for systematic reviews generates heavy load when fetching 50-200 references per query. Caching evidence responses, batching citation fetches, and optimizing query specificity reduces clinician wait times by 50-70% and keeps complex queries within acceptable latency bounds.
Caching Strategy
const cache = new Map<string, { data: any; expiry: number }>();
const TTL = { evidence: 1_800_000, citations: 3_600_000, queries: 300_000 };
async function cached(key: string, ttlKey: keyof typeof TTL, fn: () => Promise<any>) {
const entry = cache.get(key);
if (entry && entry.expiry > Date.now()) return entry.data;
const data = await fn();
cache.set(key, { data, expiry: Date.now() + TTL[ttlKey] });
return data;
}
// Citations are stable (1hr). Evidence summaries update with new studies (30 min).
Batch Operations
async function fetchCitationsBatch(client: any, citationIds: string[], batchSize = 25) {
const results = [];
for (let i = 0; i < citationIds.length; i += batchSize) {
const batch = citationIds.slice(i, i + batchSize);
const res = await Promise.all(batch.map(id => client.getCitation(id)));
results.push(...res);
if (i + batchSize < citationIds.length) await new Promise(r => setTimeout(r, 500));
}
return results;
}
Connection Pooling
import { Agent } from 'https';
const agent = new Agent({ keepAlive: true, maxSockets: 6, maxFreeSockets: 3, timeout: 30_000 });
// Moderate socket count — evidence queries are sequential, citations parallel
Rate Limit Management
async function withRateLimit(fn: () => Promise<any>): Promise<any> {
try { return await fn(); }
catch (err: any) {
if (err.status === 429) {
const retryMs = parseInt(err.headers?.['retry-after'] || '10') * 1000;
await new Promise(r => setTimeout(r, retryMs));
return fn();
}
throw err;
}
}
Monitoring
const metrics = { queries: 0, citationFetches: 0, cacheHits: 0, avgLatencyMs: 0, errors: 0 };
function track(op: 'query' | 'citation', startMs: number, cached: boolean) {
metrics[op === 'query' ? 'queries' : 'citationFetches']++;
const lat = Date.now() - startMs;
metrics.avgLatencyMs = (metrics.avgLatencyMs * (metrics.queries - 1) + lat) / metrics.queries;
if (cached) metrics.cacheHi
Prod Checklist for OpenEvidence.
ReadWriteEdit
OpenEvidence Production Checklist
Overview
OpenEvidence provides clinical decision support backed by peer-reviewed medical literature. A production integration handles Protected Health Information (PHI) subject to HIPAA, serves evidence-based answers where accuracy directly impacts patient outcomes, and must maintain complete audit trails for regulatory review. Misconfigurations can expose PHI in logs, serve stale clinical guidance, or fail compliance audits that shut down your integration entirely. This checklist enforces HIPAA-grade security, citation verification, and the SLA discipline required for healthcare-adjacent systems.
Prerequisites
- Production OpenEvidence API credentials (not trial/sandbox keys)
- Secrets manager configured (Vault, AWS Secrets Manager, or GCP Secret Manager)
- HIPAA-compliant monitoring stack (no PHI in log aggregators without BAA)
- Business Associate Agreement (BAA) executed with OpenEvidence
- Compliance officer sign-off on data flow architecture
Authentication & Secrets
- [ ] API keys stored in vault/secrets manager (never in code, env files, or CI logs)
- [ ] Key rotation schedule configured (every 90 days, with zero-downtime swap)
- [ ] Separate keys for staging vs production (staging keys cannot reach production data)
- [ ] Service account permissions scoped to query-only (no admin endpoints)
- [ ] API key exposure detection automated (scan logs/repos for leaked credentials)
API Integration
- [ ] Base URL points to production endpoint (not sandbox/staging)
- [ ] Request timeout set to 15 seconds for clinical queries (evidence synthesis is compute-heavy)
- [ ] Response time SLA monitored: p95 < 3 seconds per contractual agreement
- [ ] Pagination implemented for evidence result sets (token-based cursor)
- [ ] Clinical query payloads never include patient identifiers (de-identify before sending)
- [ ] Citation URLs in responses validated before displaying to clinicians
- [ ] Fallback behavior defined when evidence confidence score is below threshold (0.7)
Error Handling & Resilience
- [ ] Circuit breaker configured for OpenEvidence API calls (open after 3 consecutive failures)
- [ ] Retry logic with exponential backoff for 429 (rate limit) and 5xx responses
- [ ] Clinical query failures surface explicit "no evidence available" (never silent failure)
- [ ] Timeout responses distinguished from empty-result responses in UI
- [ ] Stale cache clearly labeled with retrieval timestamp when serving cached evidence
- [ ] Degraded mode displays disclaimer: "Results may not reflect latest evidence"
- [ ] All API errors logged with correlation ID (without PHI in the log entry)
Monitoring & Alerting
- [ ] API latency tracked (p50, p95, p99
Rate Limits for OpenEvidence.
ReadWriteEdit
OpenEvidence Rate Limits
Overview
OpenEvidence's clinical decision support API enforces strict rate limits to ensure reliable evidence retrieval for healthcare applications. Clinical query endpoints are throttled per API key, with lower limits on evidence synthesis calls that involve AI-powered literature analysis. In clinical settings, rate limiting directly impacts patient care workflows, so implementations must prioritize graceful degradation over retry storms. Batch research queries during off-peak hours and cache evidence summaries aggressively since medical literature changes infrequently.
Rate Limit Reference
| Endpoint |
Limit |
Window |
Scope |
| Clinical query |
30 req |
1 minute |
Per API key |
| Evidence synthesis |
10 req |
1 minute |
Per API key |
| Literature search |
60 req |
1 minute |
Per API key |
| Citation retrieval |
120 req |
1 minute |
Per API key |
| Bulk evidence export |
5 req |
1 hour |
Per API key |
Rate Limiter Implementation
class OpenEvidenceRateLimiter {
private tokens: number;
private lastRefill: number;
private readonly max: number;
private readonly refillRate: number;
private queue: Array<{ resolve: () => void }> = [];
constructor(maxPerMinute: number) {
this.max = maxPerMinute;
this.tokens = maxPerMinute;
this.lastRefill = Date.now();
this.refillRate = maxPerMinute / 60_000;
}
async acquire(): Promise<void> {
this.refill();
if (this.tokens >= 1) { this.tokens -= 1; return; }
return new Promise(resolve => this.queue.push({ resolve }));
}
private refill() {
const now = Date.now();
this.tokens = Math.min(this.max, this.tokens + (now - this.lastRefill) * this.refillRate);
this.lastRefill = now;
while (this.tokens >= 1 && this.queue.length) {
this.tokens -= 1;
this.queue.shift()!.resolve();
}
}
}
const queryLimiter = new OpenEvidenceRateLimiter(25);
const synthesisLimiter = new OpenEvidenceRateLimiter(8);
Retry Strategy
async function openEvidenceRetry<T>(
limiter: OpenEvidenceRateLimiter, fn: () => Promise<Response>, maxRetries = 3
): Promise<T> {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
await limiter.acquire();
const res = await fn();
if (res.ok) return res.json();
if (res.status === 429) {
const retryAfter = parseInt(res.headers.get("Retry-After") || "30", 10);
const jitter = Math.random() * 2000;
await new Promise(r => setTimeout(r, retryAfter * 1000 + jitter));
continue;
}
if (res.sta
Reference Architecture for OpenEvidence.
ReadWriteEditGrep
OpenEvidence Reference Architecture
Overview
Production architecture for clinical decision support integrations with OpenEvidence. Designed for healthcare platforms needing evidence-based query processing, citation-backed clinical answers, and full audit logging for regulatory compliance. Key design drivers: HIPAA-compliant data handling, deterministic citation pipelines for clinical accuracy, query audit trails for malpractice risk mitigation, and sub-second response times for point-of-care workflows where clinicians need answers during patient encounters.
Architecture Diagram
Clinician UI ──→ API Gateway (auth + HIPAA) ──→ Query Service ──→ OpenEvidence API
↓ ↓ /query
Audit Logger ──→ Audit DB Cache (Redis) /citations
↓ ↓
Analytics ──→ Usage Dashboard Citation Store ──→ Evidence DB
Service Layer
class ClinicalQueryService {
constructor(private oe: OpenEvidenceClient, private cache: CacheLayer, private audit: AuditLogger) {}
async queryEvidence(query: ClinicalQuery): Promise<EvidenceResponse> {
await this.audit.log({ type: 'query_submitted', clinicianId: query.clinicianId, queryText: query.text, timestamp: new Date() });
const cacheKey = `evidence:${this.hashQuery(query.text)}`;
const cached = await this.cache.get(cacheKey);
if (cached) { await this.audit.log({ type: 'cache_hit', cacheKey }); return cached; }
const response = await this.oe.query(query.text, { specialty: query.specialty });
await this.storeCitations(response.citations);
await this.cache.set(cacheKey, response, CACHE_CONFIG.evidence.ttl);
await this.audit.log({ type: 'query_completed', citationCount: response.citations.length });
return response;
}
async getCitationChain(citationId: string): Promise<Citation[]> {
return this.evidenceDb.getCitationWithReferences(citationId);
}
}
Caching Strategy
const CACHE_CONFIG = {
evidence: { ttl: 86400, prefix: 'evidence' }, // 24 hr — clinical evidence changes slowly
citations: { ttl: 604800, prefix: 'cite' }, // 7 days — published citations are stable
queryHist: { ttl: 3600, prefix: 'qhist' }, // 1 hr — recent query dedup for same clinician
guidelines: { ttl: 43200, prefix: 'guide' }, // 12 hr — clinical guidelines update infrequently
audit: { ttl: 0, prefix: 'audit' }, // never cached — every audit entry must persist
};
// New guideline publication events invalidate evidence cache for affected specialties
Event Pipeline
class ClinicalEventPipeline {
private queue = new Bull('clinical-events
Sdk Patterns for OpenEvidence.
ReadWriteEdit
OpenEvidence SDK Patterns
Overview
Production-ready patterns for the OpenEvidence clinical evidence API. OpenEvidence provides REST endpoints for querying medical literature, retrieving clinical guidelines, and generating evidence-based recommendations. The API authenticates via OPENEVIDENCEAPIKEY and returns structured clinical data with citation provenance. A singleton client enforces consistent auth, handles healthcare-specific errors, and preserves citation chains for audit compliance.
Singleton Client
const OE_BASE = 'https://api.openevidence.com/v1';
let _client: OpenEvidenceClient | null = null;
export function getClient(): OpenEvidenceClient {
if (!_client) {
const apiKey = process.env.OPENEVIDENCE_API_KEY;
if (!apiKey) throw new Error('OPENEVIDENCE_API_KEY must be set — get it from openevidence.com/developer');
_client = new OpenEvidenceClient(apiKey);
}
return _client;
}
class OpenEvidenceClient {
private headers: Record<string, string>;
constructor(apiKey: string) { this.headers = { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' }; }
async query(question: string, opts: { specialty?: string; maxResults?: number } = {}): Promise<EvidenceResponse> {
const res = await fetch(`${OE_BASE}/query`, { method: 'POST', headers: this.headers,
body: JSON.stringify({ question, specialty: opts.specialty, max_results: opts.maxResults ?? 10 }) });
if (!res.ok) throw new OEError(res.status, await res.text()); return res.json();
}
async getCitation(citationId: string): Promise<Citation> {
const res = await fetch(`${OE_BASE}/citations/${citationId}`, { headers: this.headers });
if (!res.ok) throw new OEError(res.status, await res.text()); return res.json();
}
}
Error Wrapper
export class OEError extends Error {
constructor(public status: number, message: string) { super(message); this.name = 'OEError'; }
}
export async function safeCall<T>(operation: string, fn: () => Promise<T>): Promise<T> {
try { return await fn(); }
catch (err: any) {
if (err instanceof OEError && err.status === 429) { await new Promise(r => setTimeout(r, 5000)); return fn(); }
if (err instanceof OEError && err.status === 401) throw new OEError(401, 'Invalid OPENEVIDENCE_API_KEY');
if (err instanceof OEError && err.status === 422) throw new OEError(422, `${operation}: query rejected — check terminology`);
throw new OEError(err.status ?? 0, `${operation} failed: ${err.message}`);
}
}
Request Builder
class OEQueryBuilder {
private body: Record<string, any> = {};
question(q: string) { this.body.question = q; return this; }
specialty(s: string) { t
Security Basics for OpenEvidence.
ReadWriteEdit
OpenEvidence Security Basics
Overview
OpenEvidence provides AI-powered clinical evidence synthesis that processes protected health information (PHI), patient queries, and medical literature references. Integrations must comply with HIPAA requirements for PHI handling, audit logging, and access controls. A breach exposes patient health questions, clinical recommendations, and potentially identifiable medical conditions. Every API interaction must be treated as a HIPAA-regulated transaction.
API Key Management
function createOpenEvidenceClient(): { apiKey: string; baseUrl: string } {
const apiKey = process.env.OPENEVIDENCE_API_KEY;
if (!apiKey) {
throw new Error("Missing OPENEVIDENCE_API_KEY — store in HIPAA-compliant secrets manager");
}
// PHI-adjacent access — enforce audit logging on every request
console.log("OpenEvidence client initialized (key suffix:", apiKey.slice(-4), ")");
return { apiKey, baseUrl: "https://api.openevidence.com/v1" };
}
Webhook Signature Verification
import crypto from "crypto";
import { Request, Response, NextFunction } from "express";
function verifyOpenEvidenceWebhook(req: Request, res: Response, next: NextFunction): void {
const signature = req.headers["x-openevidence-signature"] as string;
const secret = process.env.OPENEVIDENCE_WEBHOOK_SECRET!;
const expected = crypto.createHmac("sha256", secret).update(req.body).digest("hex");
if (!signature || !crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
res.status(401).send("Invalid signature");
return;
}
next();
}
Input Validation
import { z } from "zod";
const ClinicalQuerySchema = z.object({
query_id: z.string().uuid(),
clinical_question: z.string().min(10).max(2000),
specialty: z.enum(["oncology", "cardiology", "neurology", "general", "pediatrics", "emergency"]).optional(),
evidence_level: z.enum(["systematic_review", "rct", "cohort", "case_report", "expert_opinion"]).optional(),
include_guidelines: z.boolean().default(true),
});
function validateClinicalQuery(data: unknown) {
return ClinicalQuerySchema.parse(data);
}
Data Protection
const OPENEVIDENCE_PHI_FIELDS = ["patient_name", "date_of_birth", "mrn", "clinical_question", "diagnosis", "medication_list"];
function redactOpenEvidenceLog(record: Record<string, unknown>): Record<string, unknown> {
const redacted = { ...record };
for (const field of OPENEVIDENCE_PHI_FIELDS) {
if (field in redacted) redacted[field]
Upgrade Migration for OpenEvidence.
ReadWriteEdit
OpenEvidence Upgrade & Migration
Overview
OpenEvidence is a clinical AI platform that provides evidence-based medical answers and clinical decision support. The API exposes endpoints for clinical queries, evidence retrieval, and citation management. Tracking API changes is critical because OpenEvidence evolves its evidence grading schema, citation format, and clinical query response structure — and breaking changes in a healthcare context can surface outdated medical evidence, alter confidence scores, or remove critical safety disclaimers that downstream clinical applications depend on.
Version Detection
const OPENEVIDENCE_BASE = "https://api.openevidence.com/v1";
async function detectOpenEvidenceVersion(apiKey: string): Promise<void> {
const res = await fetch(`${OPENEVIDENCE_BASE}/status`, {
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
});
const version = res.headers.get("x-openevidence-api-version") ?? "v1";
console.log(`OpenEvidence API version: ${version}`);
// Test clinical query response schema
const queryRes = await fetch(`${OPENEVIDENCE_BASE}/query`, {
method: "POST",
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
body: JSON.stringify({ question: "What is the recommended treatment for hypertension?", max_citations: 1 }),
});
const data = await queryRes.json();
const hasStructuredCitations = data.citations?.[0]?.evidence_grade !== undefined;
console.log(`Structured citations: ${hasStructuredCitations}`);
const hasDisclaimers = data.disclaimers !== undefined;
console.log(`Disclaimers field present: ${hasDisclaimers}`);
}
Migration Checklist
- [ ] Review OpenEvidence release notes for API schema changes
- [ ] Verify clinical query response structure (answer, citations, confidence)
- [ ] Check evidence grading scale — letter grades vs. numeric scores may change
- [ ] Validate citation format (PMID references, DOI links, journal metadata)
- [ ] Test disclaimer and safety warning fields in query responses
- [ ] Update clinical specialty filters if taxonomy was expanded
- [ ] Check rate limits for clinical query endpoints (may differ by plan tier)
- [ ] Verify streaming response format if using real-time query mode
- [ ] Update evidence date range filters if temporal query syntax changed
- [ ] Run clinical validation suite against known question-answer pairs
Schema Migration
// OpenEvidence query response: flat answer → structured evidence with grading
interface OldQueryResponse {
answer: string;
citations: Array<{ title: string; url: string; source: string }>;
confidence: number;
}
interface NewQueryResponse
Webhooks Events for OpenEvidence.
ReadWriteEditGrep
OpenEvidence Webhooks & Events
Overview
OpenEvidence delivers webhook notifications for clinical evidence retrieval workflows. Subscribe to events when queries complete, evidence bases are updated, new citations are added, or clinical reviews are flagged. Use these webhooks to keep clinical decision support systems current and trigger downstream audit workflows in real time.
Webhook Registration
const response = await fetch("https://api.openevidence.com/v1/webhooks", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.OPENEVIDENCE_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
url: "https://yourapp.com/webhooks/openevidence",
events: ["query.completed", "evidence.updated", "citation.added", "review.flagged"],
secret: process.env.OPENEVIDENCE_WEBHOOK_SECRET,
}),
});
Signature Verification
import crypto from "crypto";
import { Request, Response, NextFunction } from "express";
function verifyOpenEvidenceSignature(req: Request, res: Response, next: NextFunction) {
const signature = req.headers["x-openevidence-signature"] as string;
const expected = crypto.createHmac("sha256", process.env.OPENEVIDENCE_WEBHOOK_SECRET!)
.update(req.body).digest("hex");
if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
return res.status(401).json({ error: "Invalid signature" });
}
next();
}
Event Handler
import express from "express";
const app = express();
app.post("/webhooks/openevidence", express.raw({ type: "application/json" }), verifyOpenEvidenceSignature, (req, res) => {
const event = JSON.parse(req.body.toString());
res.status(200).json({ received: true });
switch (event.type) {
case "query.completed":
deliverResults(event.data.query_id, event.data.evidence_count); break;
case "evidence.updated":
refreshClinicalCache(event.data.topic_id, event.data.revision); break;
case "citation.added":
indexCitation(event.data.citation_id, event.data.pubmed_id); break;
case "review.flagged":
escalateReview(event.data.review_id, event.data.flag_reason); break;
}
});
Event Types
| Event |
Payload Fields |
Use Case |
query.completed |
queryid, evidencecount, confidence |
Deliver clinical answers to requester |
evidence.updated |
topicid, revision, sourceschanged
Ready to use openevidence-pack?
|
|
|