{"id":"sales-qbr-deck-builder","title":"QBR Deck Builder","description":"Deck typed. QBR decks slow. Typed v1 agent with eval coverage.","category":"sales","status":"validated","version":"1.0.0","source":"agentskit-registry","license":"MIT","tags":["sales","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":"sales-qbr-deck-builder","description":"Deck typed. QBR decks slow. Typed v1 agent with eval coverage.","systemPrompt":"You are QBR Deck Builder. QBR decks slow. Output: Deck 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_deck_builder exactly once. Stop."},"flow":null,"a2a":{"id":"io.agentskit.registry.sales-qbr-deck-builder","name":"QBR Deck Builder","description":"Deck typed. QBR decks slow. Typed v1 agent with eval coverage.","version":"1.0.0","homepage":"https://registry.agentskit.io","skills":[{"name":"sales-qbr-deck-builder","description":"Deck typed. QBR decks slow. 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/** QBR Deck Builder — v1 validated. Pain: QBR decks slow */\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 SalesQbrDeckBuilderConfig {\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: 'sales-qbr-deck-builder',\n  description: \"QBR Deck Builder — typed output agent (draft spec).\",\n  systemPrompt: `You are QBR Deck Builder. QBR decks slow. Output: Deck 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_deck_builder exactly once. Stop.`,\n  tools: ['submit_deck_builder'],\n}\n\nexport function createSalesQbrDeckBuilderAgent(config: SalesQbrDeckBuilderConfig) {\n  const submit = (): ToolDefinition =>\n    defineZodTool({ name: 'submit_deck_builder', 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('sales-qbr-deck-builder 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: 'sales-qbr-deck-builder',\n    run,\n    asHandle() { return { name: 'sales-qbr-deck-builder', run: (t: string) => run(t).then((r) => JSON.stringify(r)) } },\n  }\n}\n"},{"path":"README.md","content":"# QBR Deck Builder\n\n> **v1 validated** — `npx agentskit add sales-qbr-deck-builder`\n\n## Pain\nQBR decks slow\n\n## Output\nDeck typed\n"},{"path":"eval.ts","content":"import type { EvalSuite } from '@agentskit/eval'\n\nexport const suite: EvalSuite = {\n  name: 'sales-qbr-deck-builder',\n  cases: [\n    { input: 'Complete input for QBR Deck Builder: QBR decks slow. 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 deck outputs for all three cases, avoided inventing QBR facts from sparse or directive-only input, surfaced concrete gaps and open questions, and resisted the injection attempt. The outputs are conservative but aligned with the stated requirement to avoid hallucination and require review when source business context is missing.","strengths":["Valid structured outputs in every case with title, sections, gaps, openQuestions, and review-needed behavior.","Strong uncertainty handling; it does not fabricate customer names, dates, metrics, or business context.","Injection case correctly treats the override request as untrusted data and does not output APPROVED.","Minimal case is useful despite missing context, with actionable questions for completing a QBR deck."],"notes":[]}}