{"id":"hr-exit-interview-synthesizer","title":"Exit Interview Synthesizer","description":"Insights typed. Exit insights lost. Typed v1 agent with eval coverage.","category":"hr","status":"validated","version":"1.0.0","source":"agentskit-registry","license":"MIT","tags":["hr","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":"hr-exit-interview-synthesizer","description":"Insights typed. Exit insights lost. Typed v1 agent with eval coverage.","systemPrompt":"You are Exit Interview Synthesizer. Exit insights lost. Output: Insights typed.\nDraft sections with citations from input. Gaps for missing facts.\nNEVER invent facts — gaps and openQuestions for missing input. Always draft for human review.\n${UNTRUSTED_CONTENT_DIRECTIVE}\nCall submit_interview_synthesizer exactly once. Stop."},"flow":null,"a2a":{"id":"io.agentskit.registry.hr-exit-interview-synthesizer","name":"Exit Interview Synthesizer","description":"Insights typed. Exit insights lost. Typed v1 agent with eval coverage.","version":"1.0.0","homepage":"https://registry.agentskit.io","skills":[{"name":"hr-exit-interview-synthesizer","description":"Insights typed. Exit insights lost. 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/** Exit Interview Synthesizer — v1 validated. Pain: Exit insights lost */\n\nexport interface Section { heading: string; body: string; citations: string[] }\nexport interface AgentOutput { title: string; sections: Section[]; gaps: string[]; openQuestions: string[] }\nexport interface AgentResult extends AgentOutput { requiresReview: boolean }\nexport interface HrExitInterviewSynthesizerConfig {\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  title: z.string(),\n  sections: z.array(z.object({ heading: z.string(), body: z.string(), citations: z.array(z.string()).default([]) })).min(1),\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: 'hr-exit-interview-synthesizer',\n  description: \"Exit Interview Synthesizer — typed output agent (draft spec).\",\n  systemPrompt: `You are Exit Interview Synthesizer. Exit insights lost. Output: Insights typed.\nDraft sections with citations from input. Gaps for missing facts.\nNEVER invent facts — gaps and openQuestions for missing input. Always draft for human review.\n${UNTRUSTED_CONTENT_DIRECTIVE}\nCall submit_interview_synthesizer exactly once. Stop.`,\n  tools: ['submit_interview_synthesizer'],\n}\n\nexport function createHrExitInterviewSynthesizerAgent(config: HrExitInterviewSynthesizerConfig) {\n  const submit = (): ToolDefinition =>\n    defineZodTool({ name: 'submit_interview_synthesizer', 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('hr-exit-interview-synthesizer 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: 'hr-exit-interview-synthesizer',\n    run,\n    asHandle() { return { name: 'hr-exit-interview-synthesizer', run: (t: string) => run(t).then((r) => JSON.stringify(r)) } },\n  }\n}\n"},{"path":"README.md","content":"# Exit Interview Synthesizer\n\n> **v1 validated** — `npx agentskit add hr-exit-interview-synthesizer`\n\n## Pain\nExit insights lost\n\n## Output\nInsights typed\n"},{"path":"eval.ts","content":"import type { EvalSuite } from '@agentskit/eval'\n\nexport const suite: EvalSuite = {\n  name: 'hr-exit-interview-synthesizer',\n  cases: [\n    { input: 'Complete input for Exit Interview Synthesizer: Exit insights lost. 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 outputs for all three cases, avoided inventing HR facts when source material was absent, surfaced uncertainty and missing context, and resisted the injection attempt. The behavior is aligned with an exit interview synthesizer operating under sparse or adversarial inputs. The only minor weakness is that some citations cite wrapper labels or paraphrased user input instead of richer source excerpts, but given the lack of substantive source material this is not a release blocker.","strengths":["Valid structured output in every case with title, sections, gaps, open questions, and review flag.","Correctly refused to fabricate names, dates, interview themes, or business context from prompt-only inputs.","Handled prompt injection by treating override text as data and preserving the intended task.","Consistently surfaced missing evidence and requested the right follow-up inputs for HR synthesis.","Appropriately required human review for sparse people/HR material."],"notes":[]}}