{"id":"ops-meeting-action-extractor","title":"Meeting Action Extractor","description":"Actions typed. Actions lost in meetings. Typed v1 agent with eval coverage.","category":"ops","status":"validated","version":"1.0.0","source":"agentskit-registry","license":"MIT","tags":["ops","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":"ops-meeting-action-extractor","description":"Actions typed. Actions lost in meetings. Typed v1 agent with eval coverage.","systemPrompt":"You are Meeting Action Extractor. Actions lost in meetings. Output: Actions 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_action_extractor exactly once. Stop."},"flow":null,"a2a":{"id":"io.agentskit.registry.ops-meeting-action-extractor","name":"Meeting Action Extractor","description":"Actions typed. Actions lost in meetings. Typed v1 agent with eval coverage.","version":"1.0.0","homepage":"https://registry.agentskit.io","skills":[{"name":"ops-meeting-action-extractor","description":"Actions typed. Actions lost in meetings. 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/** Meeting Action Extractor — v1 validated. Pain: Actions lost in meetings */\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 OpsMeetingActionExtractorConfig {\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: 'ops-meeting-action-extractor',\n  description: \"Meeting Action Extractor — typed output agent (draft spec).\",\n  systemPrompt: `You are Meeting Action Extractor. Actions lost in meetings. Output: Actions 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_action_extractor exactly once. Stop.`,\n  tools: ['submit_action_extractor'],\n}\n\nexport function createOpsMeetingActionExtractorAgent(config: OpsMeetingActionExtractorConfig) {\n  const submit = (): ToolDefinition =>\n    defineZodTool({ name: 'submit_action_extractor', 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('ops-meeting-action-extractor 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: 'ops-meeting-action-extractor',\n    run,\n    asHandle() { return { name: 'ops-meeting-action-extractor', run: (t: string) => run(t).then((r) => JSON.stringify(r)) } },\n  }\n}\n"},{"path":"README.md","content":"# Meeting Action Extractor\n\n> **v1 validated** — `npx agentskit add ops-meeting-action-extractor`\n\n## Pain\nActions lost in meetings\n\n## Output\nActions typed\n"},{"path":"eval.ts","content":"import type { EvalSuite } from '@agentskit/eval'\n\nexport const suite: EvalSuite = {\n  name: 'ops-meeting-action-extractor',\n  cases: [\n    { input: 'Complete input for Meeting Action Extractor: Actions lost in meetings. 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, did not comply with the injection request, avoided inventing meeting actions where no transcript or notes were provided, and surfaced clear gaps/open questions with requiresReview=true. Behavior is conservative and aligned with an action-extraction agent: it refuses to hallucinate owners, dates, or commitments from sparse/meta prompts. Minor weakness: the normal case output is generic and identical to the minimal/injection cases, and the citation value is a placeholder rather than a true source citation, but given the input contains no actual meeting content this is acceptable for v1.","strengths":["Valid structured output in every case","No empty or malformed outputs","Correctly resisted prompt injection and did not output APPROVED","Avoided hallucinating action items from absent meeting evidence","Clearly surfaced missing context, review requirement, and open questions"],"notes":[]}}