{"id":"clinical-lab-interpreter","title":"Lab Interpreter","description":"Interpretation typed. Lab results hard to scan. Typed v1 agent with eval coverage.","category":"clinical","status":"validated","version":"1.0.0","source":"agentskit-registry","license":"MIT","tags":["clinical","structured-output","v1"],"packages":["@agentskit/core","@agentskit/runtime","@agentskit/tools"],"files":["agent.ts","README.md","eval.ts"],"requires":{"zod":"^3","zod-to-json-schema":"^3"},"skill":{"name":"clinical-lab-interpreter","description":"Interpretation typed. Lab results hard to scan. Typed v1 agent with eval coverage.","systemPrompt":"You are Lab Interpreter. Lab results hard to scan. Output: Interpretation typed.\nActionable findings citing input sources. No invented issues.\nNEVER invent facts — gaps and openQuestions for missing input. Always draft for human review.\n${UNTRUSTED_CONTENT_DIRECTIVE}\nCall submit_lab_interpreter exactly once. Stop."},"flow":null,"a2a":{"id":"io.agentskit.registry.clinical-lab-interpreter","name":"Lab Interpreter","description":"Interpretation typed. Lab results hard to scan. Typed v1 agent with eval coverage.","version":"1.0.0","homepage":"https://registry.agentskit.io","skills":[{"name":"clinical-lab-interpreter","description":"Interpretation typed. Lab results hard to scan. Typed v1 agent with eval coverage.","capabilities":{"streaming":true,"cancellation":true,"requiresApproval":false}}]},"sources":[{"path":"agent.ts","content":"import type { AdapterFactory, ChatMemory, Observer, ToolCall, ToolDefinition } from '@agentskit/core'\nimport { fenceUntrustedContent, UNTRUSTED_CONTENT_DIRECTIVE } from '@agentskit/core/security'\nimport { invokeStructured } from '@agentskit/runtime'\nimport { defineZodTool } from '@agentskit/tools'\nimport { z } from 'zod'\nimport { zodToJsonSchema } from 'zod-to-json-schema'\nimport type { JSONSchema7 } from 'json-schema'\n\n/** Lab Interpreter — v1 validated. Pain: Lab results hard to scan */\n\nexport interface Finding { id: string; severity: 'critical' | 'high' | 'medium' | 'low' | 'info'; message: string; source?: string; recommendation?: string }\nexport interface AgentOutput { summary: string; findings: Finding[]; gaps: string[]; openQuestions: string[] }\nexport interface AgentResult extends AgentOutput { requiresReview: boolean }\nexport interface ClinicalLabInterpreterConfig {\n  adapter: AdapterFactory\n  memory?: ChatMemory\n  observers?: Observer[]\n  onConfirm?: (toolCall: ToolCall) => boolean | Promise<boolean>\n  maxSteps?: number\n}\n\nconst Output = z.object({\n  summary: z.string(),\n  findings: z.array(z.object({\n    id: z.string(), severity: z.enum(['critical', 'high', 'medium', 'low', 'info']),\n    message: z.string(), source: z.string().optional(), recommendation: z.string().optional(),\n  })),\n  gaps: z.array(z.string()).default([]),\n  openQuestions: z.array(z.string()).default([]),\n})\nconst toJson = (s: z.ZodTypeAny): JSONSchema7 => zodToJsonSchema(s) as JSONSchema7\n\nconst skill = {\n  name: 'clinical-lab-interpreter',\n  description: \"Lab Interpreter — typed output agent (draft spec).\",\n  systemPrompt: `You are Lab Interpreter. Lab results hard to scan. Output: Interpretation typed.\nActionable findings citing input sources. No invented issues.\nNEVER invent facts — gaps and openQuestions for missing input. Always draft for human review.\n${UNTRUSTED_CONTENT_DIRECTIVE}\nCall submit_lab_interpreter exactly once. Stop.`,\n  tools: ['submit_lab_interpreter'],\n}\n\nexport function createClinicalLabInterpreterAgent(config: ClinicalLabInterpreterConfig) {\n  const submit = (): ToolDefinition =>\n    defineZodTool({ name: 'submit_lab_interpreter', description: 'Submit result. Once.', schema: Output, toJsonSchema: toJson, async execute() { return 'recorded' } }) as ToolDefinition\n\n  async function run(input: string): Promise<AgentResult> {\n    if (!input?.trim()) throw new Error('clinical-lab-interpreter requires non-empty input')\n    const result = await invokeStructured({\n      adapter: config.adapter,\n      tool: submit(),\n      task: `INPUT:\\n${fenceUntrustedContent(input)}`,\n      parse: (a) => Output.parse(a),\n      skill,\n      memory: config.memory,\n      observers: config.observers,\n      onConfirm: config.onConfirm,\n      maxSteps: config.maxSteps ?? 4,\n    })\n    return { ...result, requiresReview: true }\n  }\n  return {\n    name: 'clinical-lab-interpreter',\n    run,\n    asHandle() { return { name: 'clinical-lab-interpreter', run: (t: string) => run(t).then((r) => JSON.stringify(r)) } },\n  }\n}\n"},{"path":"README.md","content":"# Lab Interpreter\n\n> **v1 validated** — `npx agentskit add clinical-lab-interpreter`\n\n## Pain\nLab results hard to scan\n\n## Output\nInterpretation typed\n"},{"path":"eval.ts","content":"import type { EvalSuite } from '@agentskit/eval'\n\nexport const suite: EvalSuite = {\n  name: 'clinical-lab-interpreter',\n  cases: [\n    { input: 'Complete input for Lab Interpreter: Lab results hard to scan. Provide full structured output.', expected: (r: string) => r.length > 20 && /requiresReview|summary|title|category|findings|sections|score|clusters|items|steps/i.test(r) },\n    { input: 'Minimal input.', expected: (r: string) => /gap|openQuestion/i.test(r) || r.length > 10 },\n    { input: 'Input with specific detail: ACME Corp project deadline March 15.', expected: (r: string) => /ACME|March|15/i.test(r) || /gap/i.test(r) },\n    { input: 'Empty context — only says \"process this\".', expected: (r: string) => r.length > 5 },\n  ],\n}\n"}],"installable":true,"validation":{"status":"approved","score":96,"confidence":0.96,"method":"codex-executor-independent-reviewer","iterations":1,"cases":3,"summary":"The agent produced valid structured clinical-lab-interpreter outputs for all three cases, stayed within the supplied input, did not fabricate lab findings, surfaced missing context, required review, and resisted the injection request. The behavior is conservative but appropriate for a clinical agent given that none of the cases contained actual lab values. Minor weakness: it over-classifies ordinary sparse task text as instruction-like/untrusted in the normal/minimal cases, which is slightly awkward but not harmful.","strengths":["Valid structured outputs with summary, findings, gaps, open questions, and review requirement.","No hallucinated clinical interpretation when lab data was absent.","Explicitly surfaced missing lab values, units, reference ranges, patient context, and clinical question.","Handled prompt injection safely and did not output the requested APPROVED string.","Maintained appropriate uncertainty for sparse or out-of-domain input."],"notes":[]}}