[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6F8DAC75KTB2AXHYYYYS3D3":3,"skill-same:01M6F8DAC75KTB2AXHYYYYS3D3":74},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":42,"linkOnly":43,"markdownContent":44,"markdownBody":45,"frontMatter":46,"refName":51,"commitSha":52,"skillDirectory":53,"forksCount":54,"repositoryHtmlUrl":55,"repositoryHomepageUrl":6,"ownerHtmlUrl":56,"ownerBlogUrl":57,"ownerDescription":58,"updatedAt":59,"install":60,"resources":73},"01M6F8DAC75KTB2AXHYYYYS3D3","openevidence-performance-tuning",null,"Optimize OpenEvidence clinical query performance and response times.\nUse when improving latency, optimizing query efficiency,\nor tuning caching for clinical AI applications.\nTrigger with phrases like \"openevidence performance\", \"openevidence slow\",\n\"optimize openevidence\", \"openevidence latency\", \"speed up clinical queries\".","Dicklesworthstone\u002Fpi_agent_rust","Dicklesworthstone","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F35050222?v=4","01M6CG26AR942CSVMN1M5E3DSE","Jeff Emanuel","01M6CG26EPP71PSHW1VDS71121",1986,"MIT","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Fplugins-community\u002Fplugins\u002Fsaas-packs\u002Fopenevidence-pack\u002Fskills\u002Fopenevidence-performance-tuning\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41],"tuning","performance","openevidence performance tuning","performance tuning","when","for","with","trigger","io","clinical","latency","speed","efficiency","caching","query","optimize","queries","up","use","edit","write","read","applications","2026-11-10 10:12:30",false,"---\nname: openevidence-performance-tuning\ndescription: |\n  Optimize OpenEvidence clinical query performance and response times.\n  Use when improving latency, optimizing query efficiency,\n  or tuning caching for clinical AI applications.\n  Trigger with phrases like \"openevidence performance\", \"openevidence slow\",\n  \"optimize openevidence\", \"openevidence latency\", \"speed up clinical queries\".\nallowed-tools: Read, Write, Edit\nversion: 1.0.0\nlicense: MIT\nauthor: Jeremy Longshore \u003Cjeremy@intentsolutions.io>\n---\n\n# OpenEvidence Performance Tuning\n\n## Overview\nOptimize OpenEvidence clinical query performance for point-of-care response times.\n\n## Prerequisites\n- OpenEvidence integration running\n- Monitoring configured (see `openevidence-observability`)\n- Understanding of caching strategies\n- Access to performance metrics\n\n## Performance Targets\n\n| Metric | Target | Critical |\n|--------|--------|----------|\n| Clinical Query P50 | \u003C 3s | > 10s |\n| Clinical Query P95 | \u003C 8s | > 15s |\n| Clinical Query P99 | \u003C 15s | > 30s |\n| DeepConsult Start | \u003C 5s | > 15s |\n| Cache Hit Rate | > 70% | \u003C 50% |\n\n## Instructions\n\n### Step 1: Query Optimization\n```typescript\n\u002F\u002F src\u002Fservices\u002Foptimized-query.ts\n\n\u002F\u002F 1. Optimize question structure\nfunction optimizeQuestion(question: string): string {\n  \u002F\u002F Remove unnecessary words\n  let optimized = question\n    .replace(\u002F\\b(please|can you|could you|I want to know)\\b\u002Fgi, '')\n    .replace(\u002F\\s+\u002Fg, ' ')\n    .trim();\n\n  \u002F\u002F Ensure question ends with ?\n  if (!optimized.endsWith('?')) {\n    optimized += '?';\n  }\n\n  return optimized;\n}\n\n\u002F\u002F 2. Optimize context to reduce processing\nfunction optimizeContext(context: ClinicalContext): ClinicalContext {\n  return {\n    specialty: context.specialty,\n    urgency: context.urgency,\n    \u002F\u002F Only include relevant patient context\n    ...(context.patientAge && { patientAge: context.patientAge }),\n    ...(context.patientSex && { patientSex: context.patientSex }),\n    \u002F\u002F Limit conditions to top 5 most relevant\n    ...(context.relevantConditions && {\n      relevantConditions: context.relevantConditions.slice(0, 5),\n    }),\n    \u002F\u002F Limit medications to top 10\n    ...(context.currentMedications && {\n      currentMedications: context.currentMedications.slice(0, 10),\n    }),\n  };\n}\n\n\u002F\u002F 3. Optimize query options\nconst OPTIMIZED_OPTIONS = {\n  maxCitations: 5, \u002F\u002F More citations = slower response\n  includeGuidelines: true, \u002F\u002F High value, low overhead\n  includeDrugInfo: false, \u002F\u002F Only when needed\n  prioritizeRecent: true, \u002F\u002F Faster index access\n};\n```\n\n### Step 2: Intelligent Caching Layer\n```typescript\n\u002F\u002F src\u002Fcache\u002Fclinical-cache.ts\nimport { createHash } from 'crypto';\nimport Redis from 'ioredis';\n\ninterface CacheConfig {\n  redis: Redis;\n  defaultTTL: number;\n  maxEntries: number;\n}\n\ninterface CachedResponse {\n  data: any;\n  cachedAt: number;\n  ttl: number;\n  hitCount: number;\n}\n\nexport class ClinicalQueryCache {\n  private redis: Redis;\n  private defaultTTL: number;\n  private prefix = 'oe:query:';\n\n  constructor(config: CacheConfig) {\n    this.redis = config.redis;\n    this.defaultTTL = config.defaultTTL;\n  }\n\n  \u002F\u002F Generate cache key from query\n  private generateKey(question: string, context: ClinicalContext): string {\n    const normalized = JSON.stringify({\n      q: question.toLowerCase().trim(),\n      s: context.specialty,\n      u: context.urgency,\n    });\n    return this.prefix + createHash('sha256').update(normalized).digest('hex').substring(0, 16);\n  }\n\n  \u002F\u002F Determine TTL based on query type\n  private getTTL(question: string, context: ClinicalContext): number {\n    const lowerQuestion = question.toLowerCase();\n\n    \u002F\u002F Short TTL for time-sensitive queries\n    if (context.urgency === 'stat' || context.urgency === 'urgent') {\n      return 300; \u002F\u002F 5 minutes\n    }\n\n    \u002F\u002F Longer TTL for stable medical facts\n    if (lowerQuestion.includes('mechanism') ||\n        lowerQuestion.includes('pharmacokinetics') ||\n        lowerQuestion.includes('half-life')) {\n      return 86400; \u002F\u002F 24 hours\n    }\n\n    \u002F\u002F Medium TTL for treatment guidelines (may update)\n    if (lowerQuestion.includes('guideline') ||\n        lowerQuestion.includes('first-line') ||\n        lowerQuestion.includes('recommended')) {\n      return 3600; \u002F\u002F 1 hour\n    }\n\n    return this.defaultTTL;\n  }\n\n  async get(question: string, context: ClinicalContext): Promise\u003Cany | null> {\n    const key = this.generateKey(question, context);\n    const cached = await this.redis.get(key);\n\n    if (!cached) return null;\n\n    const entry: CachedResponse = JSON.parse(cached);\n\n    \u002F\u002F Increment hit count\n    entry.hitCount++;\n    await this.redis.setex(key, entry.ttl, JSON.stringify(entry));\n\n    return entry.data;\n  }\n\n  async set(\n    question: string,\n    context: ClinicalContext,\n    data: any\n  ): Promise\u003Cvoid> {\n    const key = this.generateKey(question, context);\n    const ttl = this.getTTL(question, context);\n\n    const entry: CachedResponse = {\n      data,\n      cachedAt: Date.now(),\n      ttl,\n      hitCount: 0,\n    };\n\n    await this.redis.setex(key, ttl, JSON.stringify(entry));\n  }\n\n  async invalidate(pattern?: string): Promise\u003Cnumber> {\n    const keys = await this.redis.keys(this.prefix + (pattern || '*'));\n    if (keys.length === 0) return 0;\n    return this.redis.del(...keys);\n  }\n\n  async getStats(): Promise\u003C{\n    totalKeys: number;\n    memoryUsage: string;\n    hitRate: number;\n  }> {\n    const keys = await this.redis.keys(this.prefix + '*');\n    const info = await this.redis.info('memory');\n\n    let totalHits = 0;\n    let totalEntries = 0;\n\n    for (const key of keys.slice(0, 100)) {\n      const cached = await this.redis.get(key);\n      if (cached) {\n        const entry: CachedResponse = JSON.parse(cached);\n        totalHits += entry.hitCount;\n        totalEntries++;\n      }\n    }\n\n    return {\n      totalKeys: keys.length,\n      memoryUsage: info.match(\u002Fused_memory_human:(\\S+)\u002F)?.[1] || 'unknown',\n      hitRate: totalEntries > 0 ? totalHits \u002F totalEntries : 0,\n    };\n  }\n}\n```\n\n### Step 3: Connection Pooling & Keep-Alive\n```typescript\n\u002F\u002F src\u002Fopenevidence\u002Foptimized-client.ts\nimport { OpenEvidenceClient } from '@openevidence\u002Fsdk';\nimport { Agent } from 'https';\n\n\u002F\u002F Reuse connections with keep-alive\nconst httpsAgent = new Agent({\n  keepAlive: true,\n  keepAliveMsecs: 30000,\n  maxSockets: 10,\n  maxFreeSockets: 5,\n});\n\nexport const optimizedClient = new OpenEvidenceClient({\n  apiKey: process.env.OPENEVIDENCE_API_KEY!,\n  orgId: process.env.OPENEVIDENCE_ORG_ID!,\n  httpAgent: httpsAgent,\n  timeout: 30000,\n});\n\n\u002F\u002F Pre-warm connections on startup\nexport async function warmupConnections(): Promise\u003Cvoid> {\n  console.log('[Performance] Warming up OpenEvidence connections...');\n\n  try {\n    \u002F\u002F Make a lightweight request to establish connection\n    await optimizedClient.health.check();\n    console.log('[Performance] Connection pool warmed up');\n  } catch (error) {\n    console.error('[Performance] Warmup failed:', error);\n  }\n}\n```\n\n### Step 4: Request Batching\n```typescript\n\u002F\u002F src\u002Fservices\u002Fbatch-query.ts\nimport DataLoader from 'dataloader';\n\n\u002F\u002F Batch multiple clinical queries\nconst queryBatcher = new DataLoader\u003C\n  { question: string; context: ClinicalContext },\n  ClinicalQueryResponse\n>(\n  async (queries) => {\n    \u002F\u002F OpenEvidence may support batch API in future\n    \u002F\u002F For now, parallelize within rate limits\n    const results = await Promise.all(\n      queries.map(q => optimizedClient.query({\n        question: q.question,\n        context: q.context,\n      }))\n    );\n    return results;\n  },\n  {\n    maxBatchSize: 5, \u002F\u002F Respect rate limits\n    batchScheduleFn: (callback) => setTimeout(callback, 50), \u002F\u002F 50ms window\n    cacheKeyFn: (query) => `${query.question}:${query.context.specialty}`,\n  }\n);\n\n\u002F\u002F Usage in service\nexport async function batchedQuery(\n  question: string,\n  context: ClinicalContext\n): Promise\u003CClinicalQueryResponse> {\n  return queryBatcher.load({ question, context });\n}\n```\n\n### Step 5: Response Streaming (When Available)\n```typescript\n\u002F\u002F src\u002Fservices\u002Fstreaming-query.ts\n\u002F\u002F Use streaming for faster perceived performance\n\nexport async function streamingClinicalQuery(\n  question: string,\n  context: ClinicalContext,\n  onPartialResponse: (partial: string) => void\n): Promise\u003CClinicalQueryResponse> {\n  \u002F\u002F Check if streaming is supported\n  if (optimizedClient.supportsStreaming?.()) {\n    const stream = await optimizedClient.query.stream({\n      question,\n      context,\n    });\n\n    let fullAnswer = '';\n\n    for await (const chunk of stream) {\n      fullAnswer += chunk.text;\n      onPartialResponse(fullAnswer);\n    }\n\n    return stream.finalResponse;\n  }\n\n  \u002F\u002F Fallback to regular query\n  const response = await optimizedClient.query({ question, context });\n  onPartialResponse(response.answer);\n  return response;\n}\n```\n\n### Step 6: Performance Monitoring\n```typescript\n\u002F\u002F src\u002Fmonitoring\u002Fperformance-metrics.ts\nimport { Histogram, Counter, Gauge } from 'prom-client';\n\n\u002F\u002F Latency histogram\nconst queryLatency = new Histogram({\n  name: 'openevidence_query_duration_seconds',\n  help: 'Clinical query latency',\n  labelNames: ['specialty', 'urgency', 'cached'],\n  buckets: [0.5, 1, 2, 5, 10, 15, 30],\n});\n\n\u002F\u002F Cache metrics\nconst cacheHits = new Counter({\n  name: 'openevidence_cache_hits_total',\n  help: 'Cache hit count',\n});\n\nconst cacheMisses = new Counter({\n  name: 'openevidence_cache_misses_total',\n  help: 'Cache miss count',\n});\n\n\u002F\u002F Current queue size\nconst queueSize = new Gauge({\n  name: 'openevidence_queue_size',\n  help: 'Current request queue size',\n  labelNames: ['priority'],\n});\n\n\u002F\u002F Instrumented query function\nexport async function instrumentedQuery(\n  question: string,\n  context: ClinicalContext,\n  cache: ClinicalQueryCache\n): Promise\u003CClinicalQueryResponse> {\n  const timer = queryLatency.startTimer({\n    specialty: context.specialty,\n    urgency: context.urgency,\n  });\n\n  \u002F\u002F Check cache first\n  const cached = await cache.get(question, context);\n  if (cached) {\n    cacheHits.inc();\n    timer({ cached: 'true' });\n    return cached;\n  }\n  cacheMisses.inc();\n\n  \u002F\u002F Query API\n  const response = await optimizedClient.query({ question, context });\n\n  \u002F\u002F Cache response\n  await cache.set(question, context, response);\n\n  timer({ cached: 'false' });\n  return response;\n}\n```\n\n## Performance Checklist\n- [ ] Query optimization applied\n- [ ] Caching layer configured\n- [ ] Connection pooling enabled\n- [ ] Keep-alive connections\n- [ ] Request batching where applicable\n- [ ] Monitoring metrics collecting\n- [ ] Performance baselines established\n\n## Output\n- Optimized query construction\n- Intelligent caching with TTL management\n- Connection pooling for efficiency\n- Performance metrics and monitoring\n\n## Error Handling\n| Performance Issue | Detection | Resolution |\n|-------------------|-----------|------------|\n| High P95 latency | Metrics alert | Check cache hit rate, optimize queries |\n| Low cache hit rate | \u003C 50% hits | Review TTL strategy, increase cache size |\n| Connection timeouts | Timeout errors | Check keep-alive, increase pool size |\n| Memory pressure | Redis alerts | Implement LRU eviction |\n\n## Resources\n- [Redis Caching Best Practices](https:\u002F\u002Fredis.io\u002Fdocs\u002Fmanual\u002Fclient-side-caching\u002F)\n- [DataLoader Documentation](https:\u002F\u002Fgithub.com\u002Fgraphql\u002Fdataloader)\n\n## Next Steps\nFor cost optimization, see `openevidence-cost-tuning`.\n","# OpenEvidence Performance Tuning\n\n## Overview\nOptimize OpenEvidence clinical query performance for point-of-care response times.\n\n## Prerequisites\n- OpenEvidence integration running\n- Monitoring configured (see `openevidence-observability`)\n- Understanding of caching strategies\n- Access to performance metrics\n\n## Performance Targets\n\n| Metric | Target | Critical |\n|--------|--------|----------|\n| Clinical Query P50 | \u003C 3s | > 10s |\n| Clinical Query P95 | \u003C 8s | > 15s |\n| Clinical Query P99 | \u003C 15s | > 30s |\n| DeepConsult Start | \u003C 5s | > 15s |\n| Cache Hit Rate | > 70% | \u003C 50% |\n\n## Instructions\n\n### Step 1: Query Optimization\n```typescript\n\u002F\u002F src\u002Fservices\u002Foptimized-query.ts\n\n\u002F\u002F 1. Optimize question structure\nfunction optimizeQuestion(question: string): string {\n  \u002F\u002F Remove unnecessary words\n  let optimized = question\n    .replace(\u002F\\b(please|can you|could you|I want to know)\\b\u002Fgi, '')\n    .replace(\u002F\\s+\u002Fg, ' ')\n    .trim();\n\n  \u002F\u002F Ensure question ends with ?\n  if (!optimized.endsWith('?')) {\n    optimized += '?';\n  }\n\n  return optimized;\n}\n\n\u002F\u002F 2. Optimize context to reduce processing\nfunction optimizeContext(context: ClinicalContext): ClinicalContext {\n  return {\n    specialty: context.specialty,\n    urgency: context.urgency,\n    \u002F\u002F Only include relevant patient context\n    ...(context.patientAge && { patientAge: context.patientAge }),\n    ...(context.patientSex && { patientSex: context.patientSex }),\n    \u002F\u002F Limit conditions to top 5 most relevant\n    ...(context.relevantConditions && {\n      relevantConditions: context.relevantConditions.slice(0, 5),\n    }),\n    \u002F\u002F Limit medications to top 10\n    ...(context.currentMedications && {\n      currentMedications: context.currentMedications.slice(0, 10),\n    }),\n  };\n}\n\n\u002F\u002F 3. Optimize query options\nconst OPTIMIZED_OPTIONS = {\n  maxCitations: 5, \u002F\u002F More citations = slower response\n  includeGuidelines: true, \u002F\u002F High value, low overhead\n  includeDrugInfo: false, \u002F\u002F Only when needed\n  prioritizeRecent: true, \u002F\u002F Faster index access\n};\n```\n\n### Step 2: Intelligent Caching Layer\n```typescript\n\u002F\u002F src\u002Fcache\u002Fclinical-cache.ts\nimport { createHash } from 'crypto';\nimport Redis from 'ioredis';\n\ninterface CacheConfig {\n  redis: Redis;\n  defaultTTL: number;\n  maxEntries: number;\n}\n\ninterface CachedResponse {\n  data: any;\n  cachedAt: number;\n  ttl: number;\n  hitCount: number;\n}\n\nexport class ClinicalQueryCache {\n  private redis: Redis;\n  private defaultTTL: number;\n  private prefix = 'oe:query:';\n\n  constructor(config: CacheConfig) {\n    this.redis = config.redis;\n    this.defaultTTL = config.defaultTTL;\n  }\n\n  \u002F\u002F Generate cache key from query\n  private generateKey(question: string, context: ClinicalContext): string {\n    const normalized = JSON.stringify({\n      q: question.toLowerCase().trim(),\n      s: context.specialty,\n      u: context.urgency,\n    });\n    return this.prefix + createHash('sha256').update(normalized).digest('hex').substring(0, 16);\n  }\n\n  \u002F\u002F Determine TTL based on query type\n  private getTTL(question: string, context: ClinicalContext): number {\n    const lowerQuestion = question.toLowerCase();\n\n    \u002F\u002F Short TTL for time-sensitive queries\n    if (context.urgency === 'stat' || context.urgency === 'urgent') {\n      return 300; \u002F\u002F 5 minutes\n    }\n\n    \u002F\u002F Longer TTL for stable medical facts\n    if (lowerQuestion.includes('mechanism') ||\n        lowerQuestion.includes('pharmacokinetics') ||\n        lowerQuestion.includes('half-life')) {\n      return 86400; \u002F\u002F 24 hours\n    }\n\n    \u002F\u002F Medium TTL for treatment guidelines (may update)\n    if (lowerQuestion.includes('guideline') ||\n        lowerQuestion.includes('first-line') ||\n        lowerQuestion.includes('recommended')) {\n      return 3600; \u002F\u002F 1 hour\n    }\n\n    return this.defaultTTL;\n  }\n\n  async get(question: string, context: ClinicalContext): Promise\u003Cany | null> {\n    const key = this.generateKey(question, context);\n    const cached = await this.redis.get(key);\n\n    if (!cached) return null;\n\n    const entry: CachedResponse = JSON.parse(cached);\n\n    \u002F\u002F Increment hit count\n    entry.hitCount++;\n    await this.redis.setex(key, entry.ttl, JSON.stringify(entry));\n\n    return entry.data;\n  }\n\n  async set(\n    question: string,\n    context: ClinicalContext,\n    data: any\n  ): Promise\u003Cvoid> {\n    const key = this.generateKey(question, context);\n    const ttl = this.getTTL(question, context);\n\n    const entry: CachedResponse = {\n      data,\n      cachedAt: Date.now(),\n      ttl,\n      hitCount: 0,\n    };\n\n    await this.redis.setex(key, ttl, JSON.stringify(entry));\n  }\n\n  async invalidate(pattern?: string): Promise\u003Cnumber> {\n    const keys = await this.redis.keys(this.prefix + (pattern || '*'));\n    if (keys.length === 0) return 0;\n    return this.redis.del(...keys);\n  }\n\n  async getStats(): Promise\u003C{\n    totalKeys: number;\n    memoryUsage: string;\n    hitRate: number;\n  }> {\n    const keys = await this.redis.keys(this.prefix + '*');\n    const info = await this.redis.info('memory');\n\n    let totalHits = 0;\n    let totalEntries = 0;\n\n    for (const key of keys.slice(0, 100)) {\n      const cached = await this.redis.get(key);\n      if (cached) {\n        const entry: CachedResponse = JSON.parse(cached);\n        totalHits += entry.hitCount;\n        totalEntries++;\n      }\n    }\n\n    return {\n      totalKeys: keys.length,\n      memoryUsage: info.match(\u002Fused_memory_human:(\\S+)\u002F)?.[1] || 'unknown',\n      hitRate: totalEntries > 0 ? totalHits \u002F totalEntries : 0,\n    };\n  }\n}\n```\n\n### Step 3: Connection Pooling & Keep-Alive\n```typescript\n\u002F\u002F src\u002Fopenevidence\u002Foptimized-client.ts\nimport { OpenEvidenceClient } from '@openevidence\u002Fsdk';\nimport { Agent } from 'https';\n\n\u002F\u002F Reuse connections with keep-alive\nconst httpsAgent = new Agent({\n  keepAlive: true,\n  keepAliveMsecs: 30000,\n  maxSockets: 10,\n  maxFreeSockets: 5,\n});\n\nexport const optimizedClient = new OpenEvidenceClient({\n  apiKey: process.env.OPENEVIDENCE_API_KEY!,\n  orgId: process.env.OPENEVIDENCE_ORG_ID!,\n  httpAgent: httpsAgent,\n  timeout: 30000,\n});\n\n\u002F\u002F Pre-warm connections on startup\nexport async function warmupConnections(): Promise\u003Cvoid> {\n  console.log('[Performance] Warming up OpenEvidence connections...');\n\n  try {\n    \u002F\u002F Make a lightweight request to establish connection\n    await optimizedClient.health.check();\n    console.log('[Performance] Connection pool warmed up');\n  } catch (error) {\n    console.error('[Performance] Warmup failed:', error);\n  }\n}\n```\n\n### Step 4: Request Batching\n```typescript\n\u002F\u002F src\u002Fservices\u002Fbatch-query.ts\nimport DataLoader from 'dataloader';\n\n\u002F\u002F Batch multiple clinical queries\nconst queryBatcher = new DataLoader\u003C\n  { question: string; context: ClinicalContext },\n  ClinicalQueryResponse\n>(\n  async (queries) => {\n    \u002F\u002F OpenEvidence may support batch API in future\n    \u002F\u002F For now, parallelize within rate limits\n    const results = await Promise.all(\n      queries.map(q => optimizedClient.query({\n        question: q.question,\n        context: q.context,\n      }))\n    );\n    return results;\n  },\n  {\n    maxBatchSize: 5, \u002F\u002F Respect rate limits\n    batchScheduleFn: (callback) => setTimeout(callback, 50), \u002F\u002F 50ms window\n    cacheKeyFn: (query) => `${query.question}:${query.context.specialty}`,\n  }\n);\n\n\u002F\u002F Usage in service\nexport async function batchedQuery(\n  question: string,\n  context: ClinicalContext\n): Promise\u003CClinicalQueryResponse> {\n  return queryBatcher.load({ question, context });\n}\n```\n\n### Step 5: Response Streaming (When Available)\n```typescript\n\u002F\u002F src\u002Fservices\u002Fstreaming-query.ts\n\u002F\u002F Use streaming for faster perceived performance\n\nexport async function streamingClinicalQuery(\n  question: string,\n  context: ClinicalContext,\n  onPartialResponse: (partial: string) => void\n): Promise\u003CClinicalQueryResponse> {\n  \u002F\u002F Check if streaming is supported\n  if (optimizedClient.supportsStreaming?.()) {\n    const stream = await optimizedClient.query.stream({\n      question,\n      context,\n    });\n\n    let fullAnswer = '';\n\n    for await (const chunk of stream) {\n      fullAnswer += chunk.text;\n      onPartialResponse(fullAnswer);\n    }\n\n    return stream.finalResponse;\n  }\n\n  \u002F\u002F Fallback to regular query\n  const response = await optimizedClient.query({ question, context });\n  onPartialResponse(response.answer);\n  return response;\n}\n```\n\n### Step 6: Performance Monitoring\n```typescript\n\u002F\u002F src\u002Fmonitoring\u002Fperformance-metrics.ts\nimport { Histogram, Counter, Gauge } from 'prom-client';\n\n\u002F\u002F Latency histogram\nconst queryLatency = new Histogram({\n  name: 'openevidence_query_duration_seconds',\n  help: 'Clinical query latency',\n  labelNames: ['specialty', 'urgency', 'cached'],\n  buckets: [0.5, 1, 2, 5, 10, 15, 30],\n});\n\n\u002F\u002F Cache metrics\nconst cacheHits = new Counter({\n  name: 'openevidence_cache_hits_total',\n  help: 'Cache hit count',\n});\n\nconst cacheMisses = new Counter({\n  name: 'openevidence_cache_misses_total',\n  help: 'Cache miss count',\n});\n\n\u002F\u002F Current queue size\nconst queueSize = new Gauge({\n  name: 'openevidence_queue_size',\n  help: 'Current request queue size',\n  labelNames: ['priority'],\n});\n\n\u002F\u002F Instrumented query function\nexport async function instrumentedQuery(\n  question: string,\n  context: ClinicalContext,\n  cache: ClinicalQueryCache\n): Promise\u003CClinicalQueryResponse> {\n  const timer = queryLatency.startTimer({\n    specialty: context.specialty,\n    urgency: context.urgency,\n  });\n\n  \u002F\u002F Check cache first\n  const cached = await cache.get(question, context);\n  if (cached) {\n    cacheHits.inc();\n    timer({ cached: 'true' });\n    return cached;\n  }\n  cacheMisses.inc();\n\n  \u002F\u002F Query API\n  const response = await optimizedClient.query({ question, context });\n\n  \u002F\u002F Cache response\n  await cache.set(question, context, response);\n\n  timer({ cached: 'false' });\n  return response;\n}\n```\n\n## Performance Checklist\n- [ ] Query optimization applied\n- [ ] Caching layer configured\n- [ ] Connection pooling enabled\n- [ ] Keep-alive connections\n- [ ] Request batching where applicable\n- [ ] Monitoring metrics collecting\n- [ ] Performance baselines established\n\n## Output\n- Optimized query construction\n- Intelligent caching with TTL management\n- Connection pooling for efficiency\n- Performance metrics and monitoring\n\n## Error Handling\n| Performance Issue | Detection | Resolution |\n|-------------------|-----------|------------|\n| High P95 latency | Metrics alert | Check cache hit rate, optimize queries |\n| Low cache hit rate | \u003C 50% hits | Review TTL strategy, increase cache size |\n| Connection timeouts | Timeout errors | Check keep-alive, increase pool size |\n| Memory pressure | Redis alerts | Implement LRU eviction |\n\n## Resources\n- [Redis Caching Best Practices](https:\u002F\u002Fredis.io\u002Fdocs\u002Fmanual\u002Fclient-side-caching\u002F)\n- [DataLoader Documentation](https:\u002F\u002Fgithub.com\u002Fgraphql\u002Fdataloader)\n\n## Next Steps\nFor cost optimization, see `openevidence-cost-tuning`.\n",{"name":5,"author":47,"license":15,"version":48,"description":49,"allowed-tools":50},"Jeremy Longshore \u003Cjeremy@intentsolutions.io>","1.0.0","Optimize OpenEvidence clinical query performance and response times.\nUse when improving latency, optimizing query efficiency,\nor tuning caching for clinical AI applications.\nTrigger with phrases like \"openevidence performance\", \"openevidence slow\",\n\"optimize openevidence\", \"openevidence latency\", \"speed up clinical queries\".\n","Read, Write, Edit","main","90b50ed0778745a80fd5bfb13b1843d45b9e82f7","tests\u002Fext_conformance\u002Fartifacts\u002Fplugins-community\u002Fplugins\u002Fsaas-packs\u002Fopenevidence-pack\u002Fskills\u002Fopenevidence-performance-tuning",233,"https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust","https:\u002F\u002Fgithub.com\u002FDicklesworthstone","https:\u002F\u002Fwww.jeffreyemanuel.com\u002F","Building in NY","2026-11-13 03:33:43",{"source":8,"skillName":5,"commands":61,"prompt":71,"zipAvailable":72},[62,65,68],{"tool":63,"command":64},"npx","npx skills add Dicklesworthstone\u002Fpi_agent_rust --skill openevidence-performance-tuning",{"tool":66,"command":67},"bunx","bunx skills add Dicklesworthstone\u002Fpi_agent_rust --skill openevidence-performance-tuning",{"tool":69,"command":70},"pnpm","pnpm dlx skills add Dicklesworthstone\u002Fpi_agent_rust --skill openevidence-performance-tuning","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Fplugins-community\u002Fplugins\u002Fsaas-packs\u002Fopenevidence-pack\u002Fskills\u002Fopenevidence-performance-tuning\u002FSKILL.md",true,[],[75,114,137,163,190,211],{"skillNo":76,"name":77,"nameZh":6,"description":78,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":79,"licenseFileUrl":80,"sourceHtmlUrl":81,"categories":82,"keywords":88,"publishedAt":42},"01M6FEGPPK0ZTKCCM0R3E3KS33","web-artifacts-builder","Suite of tools for creating elaborate, multi-component claude.ai HTML artifacts using modern frontend web technologies (React, Tailwind CSS, shadcn\u002Fui). Use for complex artifacts requiring state management, routing, or shadcn\u002Fui components - not for simple single-file HTML\u002FJSX artifacts.","Apache-2.0","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Futilities\u002Fweb-artifacts-builder\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Futilities\u002Fweb-artifacts-builder\u002FSKILL.md",[83],{"categoryNo":84,"categoryName":85,"taxonomyType":86,"taxonomyTypeDesc":87},"01JBSEEDCAT000000000000009","前端开发","SCENARIO","使用场景",[89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,37,107,108,109,110,111,24,112,113],"web artifacts builder","web","artifacts","artifacts builder","builder","frontend","css","components","react","component","routing","state management","state","shadcn","file","ui","Tools","Tailwind","html","single-file","simple","ui components","multi","jsx","suite",{"skillNo":115,"name":116,"nameZh":6,"description":117,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":79,"licenseFileUrl":118,"sourceHtmlUrl":119,"categories":120,"keywords":125,"publishedAt":42},"01M6FEE9VTK1W4GY21AKREJXRG","webapp-testing","Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fsecurity\u002Fwebapp-testing\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fsecurity\u002Fwebapp-testing\u002FSKILL.md",[121,124],{"categoryNo":122,"categoryName":123,"taxonomyType":86,"taxonomyTypeDesc":87},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":84,"categoryName":85,"taxonomyType":86,"taxonomyTypeDesc":87},[126,127,128,94,129,130,90,131,132,133,104,134,41,135,136,25,24],"testing","webapp testing","webapp","screenshots","playwright","debugging","toolkit","browser","logs","behavior","local",{"skillNo":138,"name":139,"nameZh":6,"description":140,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":141,"sourceHtmlUrl":142,"categories":143,"keywords":144,"publishedAt":42},"01M6FE20F7ZTQBFWKF4MPJ2SBX","neuropixels-analysis","Neuropixels neural recording analysis. Load SpikeGLX\u002FOpenEphys data, preprocess, motion correction, Kilosort4 spike sorting, quality metrics, Allen\u002FIBL curation, AI-assisted visual analysis, for Neuropixels 1.0\u002F2.0 extracellular electrophysiology. Use when working with neural recordings, spike sorting, extracellular electrophysiology, or when the user mentions Neuropixels, SpikeGLX, Open Ephys, Kilosort, quality metrics, or unit curation.","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fscientific\u002Fneuropixels-analysis\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fscientific\u002Fneuropixels-analysis\u002FSKILL.md",[],[145,146,147,148,149,150,151,152,37,153,154,155,156,157,158,159,25,160,161,162,24,23],"analysis","neuropixels analysis","spike","metrics","data","open","quality","user","recordings","Neural","motion","visual","quality metrics","unit","sorting","curation","recording","load",{"skillNo":164,"name":165,"nameZh":6,"description":166,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":79,"licenseFileUrl":167,"sourceHtmlUrl":168,"categories":169,"keywords":173,"publishedAt":42},"01M6FDP0PDK6F1GGX395C7625Z","skill-creator","Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fproductivity\u002Fskill-creator\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fproductivity\u002Fskill-creator\u002FSKILL.md",[170],{"categoryNo":171,"categoryName":172,"taxonomyType":86,"taxonomyTypeDesc":87},"01JBSEEDCAT000000000000023","Skill与智能体开发",[174,175,176,177,178,179,180,181,182,183,184,185,186,187,25,24,188,23,189],"skill creator","creator","workflows","create","update","capabilities","knowledge","tool","integrations","specialized","guide","new skill","existing skill","users","Existing","new",{"skillNo":191,"name":192,"nameZh":6,"description":193,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":194,"sourceHtmlUrl":195,"categories":196,"keywords":198,"publishedAt":42},"01M6FDM8Y7VK7NYG9SM7QPA3PW","notebooklm","Use this skill to query your Google NotebookLM notebooks directly from Claude Code for source-grounded, citation-backed answers from Gemini. Browser automation, library management, persistent auth. Drastically reduced hallucinations through document-only responses.","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fproductivity\u002Fnotebooklm\u002FLICENSE","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fproductivity\u002Fnotebooklm\u002FSKILL.md",[197],{"categoryNo":171,"categoryName":172,"taxonomyType":86,"taxonomyTypeDesc":87},[192,199,200,201,202,203,204,133,205,206,37,207,208,33,209,24,210],"google","browser automation","gemini","automation","auth","code","library","management","only","document","Citation","source",{"skillNo":212,"name":213,"nameZh":6,"description":214,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":79,"licenseFileUrl":215,"sourceHtmlUrl":216,"categories":217,"keywords":224,"publishedAt":42},"01M6FDHPXE10J3XGTCH5HBHS1M","slack-gif-creator","Knowledge and utilities for creating animated GIFs optimized for Slack. Provides constraints, validation tools, and animation concepts. Use when users request animated GIFs for Slack like \"make me a GIF of X doing Y for Slack.\"","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fenterprise-communication\u002Fslack-gif-creator\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fenterprise-communication\u002Fslack-gif-creator\u002FSKILL.md",[218,221],{"categoryNo":219,"categoryName":220,"taxonomyType":86,"taxonomyTypeDesc":87},"01JBSEEDCAT000000000000005","邮件与沟通",{"categoryNo":222,"categoryName":223,"taxonomyType":86,"taxonomyTypeDesc":87},"01JBSEEDCAT000000000000016","图像与多媒体",[225,226,227,175,228,105,229,230,180,37,231,187,232,233,234,24,235,23],"slack gif creator","slack","gif","validation","constraints","Animation","me","make","Utilities","concepts","request"]